mbed-dev library fork for STM32F100R6 microcontroller (LQFP64, 24MHz, 32kB flash, 4kB ram, 2-channel DAC, HDMI CEC, very cheap) . Use in online compiler (instead mbed library) with selected platform Nucleo F103RB.

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