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