Renesas GR-PEACH OpenCV Development / gr-peach-opencv-project-sd-card_update

Fork of gr-peach-opencv-project-sd-card by the do

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 "drivers/SPI.h"
00017 #include "platform/mbed_critical.h"
00018 
00019 #if DEVICE_SPI
00020 
00021 namespace mbed {
00022 
00023 #if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI
00024 CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> SPI::_transaction_buffer;
00025 #endif
00026 
00027 SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) :
00028         _spi(),
00029 #if DEVICE_SPI_ASYNCH
00030         _irq(this),
00031         _usage(DMA_USAGE_NEVER),
00032 #endif
00033         _bits(8),
00034         _mode(0),
00035         _hz(1000000) {
00036     // No lock needed in the constructor
00037 
00038     spi_init(&_spi, mosi, miso, sclk, ssel);
00039     aquire();
00040 }
00041 
00042 void SPI::format(int bits, int mode) {
00043     lock();
00044     _bits = bits;
00045     _mode = mode;
00046     SPI::_owner = NULL; // Not that elegant, but works. rmeyer
00047     aquire();
00048     unlock();
00049 }
00050 
00051 void SPI::frequency(int hz) {
00052     lock();
00053     _hz = hz;
00054     SPI::_owner = NULL; // Not that elegant, but works. rmeyer
00055     aquire();
00056     unlock();
00057 }
00058 
00059 SPI* SPI::_owner = NULL;
00060 SingletonPtr<PlatformMutex>  SPI::_mutex;
00061 
00062 // ignore the fact there are multiple physical spis, and always update if it wasnt us last
00063 void SPI::aquire() {
00064     lock();
00065      if (_owner != this) {
00066         spi_format(&_spi, _bits, _mode, 0);
00067         spi_frequency(&_spi, _hz);
00068         _owner = this;
00069     }
00070     unlock();
00071 }
00072 
00073 int SPI::write(int value) {
00074     lock();
00075     aquire();
00076     int ret = spi_master_write(&_spi, value);
00077     unlock();
00078     return ret;
00079 }
00080 
00081 int SPI::write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
00082     lock();
00083     aquire();
00084     int ret = spi_master_block_write(&_spi, tx_buffer, tx_length, rx_buffer, rx_length);
00085     unlock();
00086     return ret;
00087 }
00088 
00089 void SPI::lock() {
00090     _mutex->lock();
00091 }
00092 
00093 void SPI::unlock() {
00094     _mutex->unlock();
00095 }
00096 
00097 #if DEVICE_SPI_ASYNCH
00098 
00099 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)
00100 {
00101     if (spi_active(&_spi)) {
00102         return queue_transfer (tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
00103     }
00104     start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
00105     return 0;
00106 }
00107 
00108 void SPI::abort_transfer()
00109 {
00110     spi_abort_asynch(&_spi);
00111 #if TRANSACTION_QUEUE_SIZE_SPI
00112     dequeue_transaction();
00113 #endif
00114 }
00115 
00116 
00117 void SPI::clear_transfer_buffer()
00118 {
00119 #if TRANSACTION_QUEUE_SIZE_SPI
00120     _transaction_buffer.reset();
00121 #endif
00122 }
00123 
00124 void SPI::abort_all_transfers()
00125 {
00126     clear_transfer_buffer();
00127     abort_transfer();
00128 }
00129 
00130 int SPI::set_dma_usage(DMAUsage usage)
00131 {
00132     if (spi_active(&_spi)) {
00133         return -1;
00134     }
00135     _usage = usage;
00136     return  0;
00137 }
00138 
00139 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)
00140 {
00141 #if TRANSACTION_QUEUE_SIZE_SPI
00142     transaction_t t;
00143 
00144     t.tx_buffer = const_cast<void *>(tx_buffer);
00145     t.tx_length = tx_length;
00146     t.rx_buffer = rx_buffer;
00147     t.rx_length = rx_length;
00148     t.event = event;
00149     t.callback = callback;
00150     t.width = bit_width;
00151     Transaction<SPI>  transaction(this, t);
00152     if (_transaction_buffer.full()) {
00153         return -1; // the buffer is full
00154     } else {
00155         core_util_critical_section_enter();
00156         _transaction_buffer.push(transaction);
00157         if (!spi_active(&_spi)) {
00158             dequeue_transaction();
00159         }
00160         core_util_critical_section_exit();
00161         return 0;
00162     }
00163 #else
00164     return -1;
00165 #endif
00166 }
00167 
00168 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)
00169 {
00170     aquire();
00171     _callback = callback;
00172     _irq.callback(&SPI::irq_handler_asynch);
00173     spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage);
00174 }
00175 
00176 #if TRANSACTION_QUEUE_SIZE_SPI
00177 
00178 void SPI::start_transaction(transaction_t *data)
00179 {
00180     start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event);
00181 }
00182 
00183 void SPI::dequeue_transaction()
00184 {
00185     Transaction<SPI>  t;
00186     if (_transaction_buffer.pop(t)) {
00187         SPI* obj = t.get_object();
00188         transaction_t* data = t.get_transaction();
00189         obj->start_transaction(data);
00190     }
00191 }
00192 
00193 #endif
00194 
00195 void SPI::irq_handler_asynch(void)
00196 {
00197     int event = spi_irq_handler_asynch(&_spi);
00198     if (_callback && (event & SPI_EVENT_ALL)) {
00199         _callback.call(event & SPI_EVENT_ALL);
00200     }
00201 #if TRANSACTION_QUEUE_SIZE_SPI
00202     if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) {
00203         // SPI peripheral is free (event happend), dequeue transaction
00204         dequeue_transaction();
00205     }
00206 #endif
00207 }
00208 
00209 #endif
00210 
00211 } // namespace mbed
00212 
00213 #endif
00214