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 mbed-dev 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_ASYNCH 00020 #include "platform/mbed_power_mgmt.h" 00021 #endif 00022 00023 #if DEVICE_SPI 00024 00025 namespace mbed { 00026 00027 #if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI 00028 CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> SPI::_transaction_buffer; 00029 #endif 00030 00031 SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) : 00032 _spi(), 00033 #if DEVICE_SPI_ASYNCH 00034 _irq(this), 00035 _usage(DMA_USAGE_NEVER), 00036 _deep_sleep_locked(false), 00037 #endif 00038 _bits(8), 00039 _mode(0), 00040 _hz(1000000), 00041 _write_fill(SPI_FILL_CHAR) 00042 { 00043 // No lock needed in the constructor 00044 00045 spi_init(&_spi, mosi, miso, sclk, ssel); 00046 _acquire(); 00047 } 00048 00049 void SPI::format(int bits, int mode) 00050 { 00051 lock(); 00052 _bits = bits; 00053 _mode = mode; 00054 // If changing format while you are the owner then just 00055 // update format, but if owner is changed then even frequency should be 00056 // updated which is done by acquire. 00057 if (_owner == this) { 00058 spi_format(&_spi, _bits, _mode, 0); 00059 } else { 00060 _acquire(); 00061 } 00062 unlock(); 00063 } 00064 00065 void SPI::frequency(int hz) 00066 { 00067 lock(); 00068 _hz = hz; 00069 // If changing format while you are the owner then just 00070 // update frequency, but if owner is changed then even frequency should be 00071 // updated which is done by acquire. 00072 if (_owner == this) { 00073 spi_frequency(&_spi, _hz); 00074 } else { 00075 _acquire(); 00076 } 00077 unlock(); 00078 } 00079 00080 SPI *SPI::_owner = NULL; 00081 SingletonPtr<PlatformMutex> SPI::_mutex; 00082 00083 // ignore the fact there are multiple physical spis, and always update if it wasn't us last 00084 void SPI::aquire() 00085 { 00086 lock(); 00087 if (_owner != this) { 00088 spi_format(&_spi, _bits, _mode, 0); 00089 spi_frequency(&_spi, _hz); 00090 _owner = this; 00091 } 00092 unlock(); 00093 } 00094 00095 // Note: Private function with no locking 00096 void SPI::_acquire() 00097 { 00098 if (_owner != this) { 00099 spi_format(&_spi, _bits, _mode, 0); 00100 spi_frequency(&_spi, _hz); 00101 _owner = this; 00102 } 00103 } 00104 00105 int SPI::write(int value) 00106 { 00107 lock(); 00108 _acquire(); 00109 int ret = spi_master_write(&_spi, value); 00110 unlock(); 00111 return ret; 00112 } 00113 00114 int SPI::write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) 00115 { 00116 lock(); 00117 _acquire(); 00118 int ret = spi_master_block_write(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, _write_fill); 00119 unlock(); 00120 return ret; 00121 } 00122 00123 void SPI::lock() 00124 { 00125 _mutex->lock(); 00126 } 00127 00128 void SPI::unlock() 00129 { 00130 _mutex->unlock(); 00131 } 00132 00133 void SPI::set_default_write_value(char data) 00134 { 00135 lock(); 00136 _write_fill = data; 00137 unlock(); 00138 } 00139 00140 #if DEVICE_SPI_ASYNCH 00141 00142 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) 00143 { 00144 if (spi_active(&_spi)) { 00145 return queue_transfer (tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); 00146 } 00147 start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); 00148 return 0; 00149 } 00150 00151 void SPI::abort_transfer() 00152 { 00153 spi_abort_asynch(&_spi); 00154 unlock_deep_sleep(); 00155 #if TRANSACTION_QUEUE_SIZE_SPI 00156 dequeue_transaction(); 00157 #endif 00158 } 00159 00160 00161 void SPI::clear_transfer_buffer() 00162 { 00163 #if TRANSACTION_QUEUE_SIZE_SPI 00164 _transaction_buffer.reset(); 00165 #endif 00166 } 00167 00168 void SPI::abort_all_transfers() 00169 { 00170 clear_transfer_buffer(); 00171 abort_transfer(); 00172 } 00173 00174 int SPI::set_dma_usage(DMAUsage usage) 00175 { 00176 if (spi_active(&_spi)) { 00177 return -1; 00178 } 00179 _usage = usage; 00180 return 0; 00181 } 00182 00183 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) 00184 { 00185 #if TRANSACTION_QUEUE_SIZE_SPI 00186 transaction_t t; 00187 00188 t.tx_buffer = const_cast<void *>(tx_buffer); 00189 t.tx_length = tx_length; 00190 t.rx_buffer = rx_buffer; 00191 t.rx_length = rx_length; 00192 t.event = event; 00193 t.callback = callback; 00194 t.width = bit_width; 00195 Transaction<SPI> transaction(this, t); 00196 if (_transaction_buffer.full()) { 00197 return -1; // the buffer is full 00198 } else { 00199 core_util_critical_section_enter(); 00200 _transaction_buffer.push(transaction); 00201 if (!spi_active(&_spi)) { 00202 dequeue_transaction(); 00203 } 00204 core_util_critical_section_exit(); 00205 return 0; 00206 } 00207 #else 00208 return -1; 00209 #endif 00210 } 00211 00212 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) 00213 { 00214 lock_deep_sleep(); 00215 _acquire(); 00216 _callback = callback; 00217 _irq.callback(&SPI::irq_handler_asynch); 00218 spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event, _usage); 00219 } 00220 00221 void SPI::lock_deep_sleep() 00222 { 00223 if (_deep_sleep_locked == false) { 00224 sleep_manager_lock_deep_sleep(); 00225 _deep_sleep_locked = true; 00226 } 00227 } 00228 00229 void SPI::unlock_deep_sleep() 00230 { 00231 if (_deep_sleep_locked == true) { 00232 sleep_manager_unlock_deep_sleep(); 00233 _deep_sleep_locked = false; 00234 } 00235 } 00236 00237 #if TRANSACTION_QUEUE_SIZE_SPI 00238 00239 void SPI::start_transaction(transaction_t *data) 00240 { 00241 start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event); 00242 } 00243 00244 void SPI::dequeue_transaction() 00245 { 00246 Transaction<SPI> t; 00247 if (_transaction_buffer.pop(t)) { 00248 SPI *obj = t.get_object(); 00249 transaction_t *data = t.get_transaction(); 00250 obj->start_transaction(data); 00251 } 00252 } 00253 00254 #endif 00255 00256 void SPI::irq_handler_asynch(void) 00257 { 00258 int event = spi_irq_handler_asynch(&_spi); 00259 if (_callback && (event & SPI_EVENT_ALL)) { 00260 unlock_deep_sleep(); 00261 _callback.call(event & SPI_EVENT_ALL); 00262 } 00263 #if TRANSACTION_QUEUE_SIZE_SPI 00264 if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) { 00265 // SPI peripheral is free (event happened), dequeue transaction 00266 dequeue_transaction(); 00267 } 00268 #endif 00269 } 00270 00271 #endif 00272 00273 } // namespace mbed 00274 00275 #endif
Generated on Tue Jul 12 2022 19:10:22 by
 1.7.2 
    