Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of gr-peach-opencv-project-sd-card by
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
Generated on Tue Jul 12 2022 14:47:36 by
