mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPI.h Source File

SPI.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2015 ARM Limited
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #ifndef MBED_SPI_H
00018 #define MBED_SPI_H
00019 
00020 #include "platform/platform.h"
00021 
00022 #if DEVICE_SPI || defined(DOXYGEN_ONLY)
00023 
00024 #include "platform/PlatformMutex.h"
00025 #include "hal/spi_api.h"
00026 #include "platform/SingletonPtr.h"
00027 #include "platform/NonCopyable.h"
00028 
00029 #if DEVICE_SPI_ASYNCH
00030 #include "platform/CThunk.h"
00031 #include "hal/dma_api.h"
00032 #include "platform/CircularBuffer.h"
00033 #include "platform/FunctionPointer.h"
00034 #include "platform/Transaction.h"
00035 #endif
00036 
00037 namespace mbed {
00038 /** \addtogroup drivers */
00039 
00040 /** A SPI Master, used for communicating with SPI slave devices.
00041  *
00042  * The default format is set to 8-bits, mode 0, and a clock frequency of 1MHz.
00043  *
00044  * Most SPI devices will also require Chip Select and Reset signals. These
00045  * can be controlled using DigitalOut pins.
00046  *
00047  * @note Synchronization level: Thread safe
00048  *
00049  * Example of how to send a byte to a SPI slave and record the response:
00050  * @code
00051  * #include "mbed.h"
00052  *
00053  * SPI device(SPI_MOSI, SPI_MISO, SPI_SCLK)
00054  *
00055  * DigitalOut chip_select(SPI_CS);
00056  *
00057  * int main() {
00058  *     device.lock();
00059  *     chip_select = 0;
00060  *
00061  *     int response = device.write(0xFF);
00062  *
00063  *     chip_select = 1;
00064  *     device.unlock();
00065  * }
00066  * @endcode
00067  *
00068  * Example using hardware Chip Select line:
00069  * @code
00070  * #include "mbed.h"
00071  *
00072  * SPI device(SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS)
00073  *
00074  * int main() {
00075  *     device.lock();
00076  *     int response = device.write(0xFF);
00077  *     device.unlock();
00078  * }
00079  * @endcode
00080  * @ingroup drivers
00081  */
00082 class SPI : private NonCopyable<SPI> {
00083 
00084 public:
00085 
00086     /** Create a SPI master connected to the specified pins.
00087      *
00088      *  @note You can specify mosi or miso as NC if not used.
00089      *
00090      *  @param mosi SPI Master Out, Slave In pin.
00091      *  @param miso SPI Master In, Slave Out pin.
00092      *  @param sclk SPI Clock pin.
00093      *  @param ssel SPI Chip Select pin.
00094      */
00095     SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel = NC);
00096     virtual ~SPI();
00097 
00098     /** Configure the data transmission format.
00099      *
00100      *  @param bits Number of bits per SPI frame (4 - 16).
00101      *  @param mode Clock polarity and phase mode (0 - 3).
00102      *
00103      * @code
00104      * mode | POL PHA
00105      * -----+--------
00106      *   0  |  0   0
00107      *   1  |  0   1
00108      *   2  |  1   0
00109      *   3  |  1   1
00110      * @endcode
00111      */
00112     void format(int bits, int mode = 0);
00113 
00114     /** Set the SPI bus clock frequency.
00115      *
00116      *  @param hz Clock frequency in Hz (default = 1MHz).
00117      */
00118     void frequency(int hz = 1000000);
00119 
00120     /** Write to the SPI Slave and return the response.
00121      *
00122      *  @param value Data to be sent to the SPI slave.
00123      *
00124      *  @return Response from the SPI slave.
00125      */
00126     virtual int write(int value);
00127 
00128     /** Write to the SPI Slave and obtain the response.
00129      *
00130      *  The total number of bytes sent and received will be the maximum of
00131      *  tx_length and rx_length. The bytes written will be padded with the
00132      *  value 0xff.
00133      *
00134      *  @param tx_buffer Pointer to the byte-array of data to write to the device.
00135      *  @param tx_length Number of bytes to write, may be zero.
00136      *  @param rx_buffer Pointer to the byte-array of data to read from the device.
00137      *  @param rx_length Number of bytes to read, may be zero.
00138      *  @return
00139      *      The number of bytes written and read from the device. This is
00140      *      maximum of tx_length and rx_length.
00141      */
00142     virtual int write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length);
00143 
00144     /** Acquire exclusive access to this SPI bus.
00145      */
00146     virtual void lock(void);
00147 
00148     /** Release exclusive access to this SPI bus.
00149      */
00150     virtual void unlock(void);
00151 
00152     /** Set default write data.
00153       * SPI requires the master to send some data during a read operation.
00154       * Different devices may require different default byte values.
00155       * For example: A SD Card requires default bytes to be 0xFF.
00156       *
00157       * @param data Default character to be transmitted during a read operation.
00158       */
00159     void set_default_write_value(char data);
00160 
00161 #if DEVICE_SPI_ASYNCH
00162 
00163     /** Start non-blocking SPI transfer using 8bit buffers.
00164      *
00165      * This function locks the deep sleep until any event has occurred.
00166      *
00167      * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
00168      *                  the default SPI value is sent.
00169      * @param tx_length The length of TX buffer in bytes.
00170      * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
00171      *                  received data are ignored.
00172      * @param rx_length The length of RX buffer in bytes.
00173      * @param callback  The event callback function.
00174      * @param event     The event mask of events to modify. @see spi_api.h for SPI events.
00175      *
00176      * @return Operation result.
00177      * @retval 0 If the transfer has started.
00178      * @retval -1 If SPI peripheral is busy.
00179      */
00180     template<typename Type>
00181     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)
00182     {
00183         if (spi_active(&_spi)) {
00184             return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, sizeof(Type) * 8, callback, event);
00185         }
00186         start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, sizeof(Type) * 8, callback, event);
00187         return 0;
00188     }
00189 
00190     /** Abort the on-going SPI transfer, and continue with transfers in the queue, if any.
00191      */
00192     void abort_transfer();
00193 
00194     /** Clear the queue of transfers.
00195      */
00196     void clear_transfer_buffer();
00197 
00198     /** Clear the queue of transfers and abort the on-going transfer.
00199      */
00200     void abort_all_transfers();
00201 
00202     /** Configure DMA usage suggestion for non-blocking transfers.
00203      *
00204      *  @param usage The usage DMA hint for peripheral.
00205      *
00206      *  @return Result of the operation.
00207      *  @retval 0 The usage was set.
00208      *  @retval -1 Usage cannot be set as there is an ongoing transaction.
00209      */
00210     int set_dma_usage(DMAUsage usage);
00211 
00212 #if !defined(DOXYGEN_ONLY)
00213 protected:
00214     /** SPI interrupt handler.
00215      */
00216     void irq_handler_asynch(void);
00217 
00218     /** Start the transfer or put it on the queue.
00219      *
00220      * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
00221      *                  the default SPI value is sent
00222      * @param tx_length The length of TX buffer in bytes.
00223      * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
00224      *                  received data are ignored.
00225      * @param rx_length The length of RX buffer in bytes.
00226      * @param bit_width The buffers element width in bits.
00227      * @param callback  The event callback function.
00228      * @param event     The event mask of events to modify.
00229      *
00230      * @return Operation success.
00231      * @retval 0 A transfer was started or added to the queue.
00232      * @retval -1 Transfer can't be added because queue is full.
00233      */
00234     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);
00235 
00236     /** Put a transfer on the transfer queue.
00237      *
00238      * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
00239      *                  the default SPI value is sent.
00240      * @param tx_length The length of TX buffer in bytes.
00241      * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
00242      *                  received data are ignored.
00243      * @param rx_length The length of RX buffer in bytes.
00244      * @param bit_width The buffers element width in bits.
00245      * @param callback  The event callback function.
00246      * @param event     The event mask of events to modify.
00247      *
00248      * @return Operation success.
00249      * @retval 0 A transfer was added to the queue.
00250      * @retval -1 Transfer can't be added because queue is full.
00251      */
00252     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);
00253 
00254     /** Configure a callback, SPI peripheral, and initiate a new transfer.
00255      *
00256      * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
00257      *                  the default SPI value is sent.
00258      * @param tx_length The length of TX buffer in bytes.
00259      * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
00260      *                  received data are ignored.
00261      * @param rx_length The length of RX buffer in bytes.
00262      * @param bit_width The buffers element width.
00263      * @param callback  The event callback function.
00264      * @param event     The event mask of events to modify.
00265      */
00266     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);
00267 
00268 private:
00269     /** Lock deep sleep only if it is not yet locked */
00270     void lock_deep_sleep();
00271 
00272     /** Unlock deep sleep in case it is locked */
00273     void unlock_deep_sleep();
00274 
00275 
00276 #if TRANSACTION_QUEUE_SIZE_SPI
00277 
00278     /** Start a new transaction.
00279      *
00280      *  @param data Transaction data.
00281      */
00282     void start_transaction(transaction_t *data);
00283 
00284     /** Dequeue a transaction and start the transfer if there was one pending.
00285      */
00286     void dequeue_transaction();
00287 
00288     /* Queue of pending transfers */
00289     static CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> _transaction_buffer;
00290 #endif
00291 
00292 #endif //!defined(DOXYGEN_ONLY)
00293 
00294 #endif //DEVICE_SPI_ASYNCH
00295 
00296 #if !defined(DOXYGEN_ONLY)
00297 protected:
00298     /* Internal SPI object identifying the resources */
00299     spi_t _spi;
00300 
00301 #if DEVICE_SPI_ASYNCH
00302     /* Interrupt */
00303     CThunk<SPI>  _irq;
00304     /* Interrupt handler callback */
00305     event_callback_t _callback;
00306     /* Current preferred DMA mode @see dma_api.h */
00307     DMAUsage _usage;
00308     /* Current sate of the sleep manager */
00309     bool _deep_sleep_locked;
00310 #endif
00311 
00312     /* Take over the physical SPI and apply our settings (thread safe) */
00313     void aquire(void);
00314     /* Current user of the SPI */
00315     static SPI *_owner;
00316     /* Used by lock and unlock for thread safety */
00317     static SingletonPtr<PlatformMutex>  _mutex;
00318     /* Size of the SPI frame */
00319     int _bits;
00320     /* Clock polairy and phase */
00321     int _mode;
00322     /* Clock frequency */
00323     int _hz;
00324     /* Default character used for NULL transfers */
00325     char _write_fill;
00326 
00327 private:
00328     /** Private acquire function without locking/unlocking.
00329      *  Implemented in order to avoid duplicate locking and boost performance.
00330      */
00331     void _acquire(void);
00332 
00333 #endif //!defined(DOXYGEN_ONLY)
00334 };
00335 
00336 } // namespace mbed
00337 
00338 #endif
00339 
00340 #endif