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