mbed library sources

Fork of mbed-src by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPI.cpp Source File

SPI.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "SPI.h"
00017 
00018 #if DEVICE_SPI
00019 
00020 namespace mbed {
00021 
00022 #if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI
00023 CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> SPI::_transaction_buffer;
00024 #endif
00025 
00026 SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) :
00027         _spi(),
00028 #if DEVICE_SPI_ASYNCH
00029         _irq(this),
00030         _usage(DMA_USAGE_NEVER),
00031 #endif
00032         _bits(8),
00033         _mode(0),
00034         _hz(1000000) {
00035     spi_init(&_spi, mosi, miso, sclk, ssel);
00036     spi_format(&_spi, _bits, _mode, 0);
00037     spi_frequency(&_spi, _hz);
00038 }
00039 
00040 void SPI::format(int bits, int mode) {
00041     _bits = bits;
00042     _mode = mode;
00043     SPI::_owner = NULL; // Not that elegant, but works. rmeyer
00044     aquire();
00045 }
00046 
00047 void SPI::frequency(int hz) {
00048     _hz = hz;
00049     SPI::_owner = NULL; // Not that elegant, but works. rmeyer
00050     aquire();
00051 }
00052 
00053 SPI* SPI::_owner = NULL;
00054 
00055 // ignore the fact there are multiple physical spis, and always update if it wasnt us last
00056 void SPI::aquire() {
00057      if (_owner != this) {
00058         spi_format(&_spi, _bits, _mode, 0);
00059         spi_frequency(&_spi, _hz);
00060         _owner = this;
00061     }
00062 }
00063 
00064 int SPI::write(int value) {
00065     aquire();
00066     return spi_master_write(&_spi, value);
00067 }
00068 
00069 #if DEVICE_SPI_ASYNCH
00070 
00071 int SPI::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)
00072 {
00073     if (spi_active(&_spi)) {
00074         return queue_transfer (tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
00075     }
00076     start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
00077     return 0;
00078 }
00079 
00080 void SPI::abort_transfer()
00081 {
00082     spi_abort_asynch(&_spi);
00083 #if TRANSACTION_QUEUE_SIZE_SPI
00084     dequeue_transaction();
00085 #endif
00086 }
00087 
00088 
00089 void SPI::clear_transfer_buffer()
00090 {
00091 #if TRANSACTION_QUEUE_SIZE_SPI
00092     _transaction_buffer.reset();
00093 #endif
00094 }
00095 
00096 void SPI::abort_all_transfers()
00097 {
00098     clear_transfer_buffer();
00099     abort_transfer();
00100 }
00101 
00102 int SPI::set_dma_usage(DMAUsage usage)
00103 {
00104     if (spi_active(&_spi)) {
00105         return -1;
00106     }
00107     _usage = usage;
00108     return  0;
00109 }
00110 
00111 int SPI::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)
00112 {
00113 #if TRANSACTION_QUEUE_SIZE_SPI
00114     transaction_t t;
00115 
00116     t.tx_buffer = const_cast<void *>(tx_buffer);
00117     t.tx_length = tx_length;
00118     t.rx_buffer = rx_buffer;
00119     t.rx_length = rx_length;
00120     t.event = event;
00121     t.callback = callback;
00122     t.width = bit_width;
00123     Transaction<SPI>  transaction(this, t);
00124     if (_transaction_buffer.full()) {
00125         return -1; // the buffer is full
00126     } else {
00127         _transaction_buffer.push(transaction);
00128         return 0;
00129     }
00130 #else
00131     return -1;
00132 #endif
00133 }
00134 
00135 void SPI::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)
00136 {
00137     aquire();
00138     _callback = callback;
00139     _irq.callback(&SPI::irq_handler_asynch);
00140     spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage);
00141 }
00142 
00143 #if TRANSACTION_QUEUE_SIZE_SPI
00144 
00145 void SPI::start_transaction(transaction_t *data)
00146 {
00147     start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event);
00148 }
00149 
00150 void SPI::dequeue_transaction()
00151 {
00152     Transaction<SPI>  t;
00153     if (_transaction_buffer.pop(t)) {
00154         SPI* obj = t.get_object();
00155         transaction_t* data = t.get_transaction();
00156         obj->start_transaction(data);
00157     }
00158 }
00159 
00160 #endif
00161 
00162 void SPI::irq_handler_asynch(void)
00163 {
00164     int event = spi_irq_handler_asynch(&_spi);
00165     if (_callback && (event & SPI_EVENT_ALL)) {
00166         _callback.call(event & SPI_EVENT_ALL);
00167     }
00168 #if TRANSACTION_QUEUE_SIZE_SPI
00169     if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) {
00170         // SPI peripheral is free (event happend), dequeue transaction
00171         dequeue_transaction();
00172     }
00173 #endif
00174 }
00175 
00176 #endif
00177 
00178 } // namespace mbed
00179 
00180 #endif