mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
SPI.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #include "drivers/SPI.h" 00018 #include "platform/mbed_critical.h" 00019 00020 #if DEVICE_SPI_ASYNCH 00021 #include "platform/mbed_power_mgmt.h" 00022 #endif 00023 00024 #if DEVICE_SPI 00025 00026 namespace mbed { 00027 00028 #if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI 00029 CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> SPI::_transaction_buffer; 00030 #endif 00031 00032 SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) : 00033 _spi(), 00034 #if DEVICE_SPI_ASYNCH 00035 _irq(this), 00036 _usage(DMA_USAGE_NEVER), 00037 _deep_sleep_locked(false), 00038 #endif 00039 _bits(8), 00040 _mode(0), 00041 _hz(1000000), 00042 _write_fill(SPI_FILL_CHAR) 00043 { 00044 // No lock needed in the constructor 00045 spi_init(&_spi, mosi, miso, sclk, ssel); 00046 } 00047 00048 SPI::~SPI() 00049 { 00050 if (_owner == this) { 00051 _owner = NULL; 00052 } 00053 } 00054 00055 void SPI::format(int bits, int mode) 00056 { 00057 lock(); 00058 _bits = bits; 00059 _mode = mode; 00060 // If changing format while you are the owner then just 00061 // update format, but if owner is changed then even frequency should be 00062 // updated which is done by acquire. 00063 if (_owner == this) { 00064 spi_format(&_spi, _bits, _mode, 0); 00065 } else { 00066 _acquire(); 00067 } 00068 unlock(); 00069 } 00070 00071 void SPI::frequency(int hz) 00072 { 00073 lock(); 00074 _hz = hz; 00075 // If changing format while you are the owner then just 00076 // update frequency, but if owner is changed then even frequency should be 00077 // updated which is done by acquire. 00078 if (_owner == this) { 00079 spi_frequency(&_spi, _hz); 00080 } else { 00081 _acquire(); 00082 } 00083 unlock(); 00084 } 00085 00086 SPI *SPI::_owner = NULL; 00087 SingletonPtr<PlatformMutex> SPI::_mutex; 00088 00089 // ignore the fact there are multiple physical spis, and always update if it wasn't us last 00090 void SPI::aquire() 00091 { 00092 lock(); 00093 if (_owner != this) { 00094 spi_format(&_spi, _bits, _mode, 0); 00095 spi_frequency(&_spi, _hz); 00096 _owner = this; 00097 } 00098 unlock(); 00099 } 00100 00101 // Note: Private function with no locking 00102 void SPI::_acquire() 00103 { 00104 if (_owner != this) { 00105 spi_format(&_spi, _bits, _mode, 0); 00106 spi_frequency(&_spi, _hz); 00107 _owner = this; 00108 } 00109 } 00110 00111 int SPI::write(int value) 00112 { 00113 lock(); 00114 _acquire(); 00115 int ret = spi_master_write(&_spi, value); 00116 unlock(); 00117 return ret; 00118 } 00119 00120 int SPI::write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) 00121 { 00122 lock(); 00123 _acquire(); 00124 int ret = spi_master_block_write(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, _write_fill); 00125 unlock(); 00126 return ret; 00127 } 00128 00129 void SPI::lock() 00130 { 00131 _mutex->lock(); 00132 } 00133 00134 void SPI::unlock() 00135 { 00136 _mutex->unlock(); 00137 } 00138 00139 void SPI::set_default_write_value(char data) 00140 { 00141 lock(); 00142 _write_fill = data; 00143 unlock(); 00144 } 00145 00146 #if DEVICE_SPI_ASYNCH 00147 00148 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) 00149 { 00150 if (spi_active(&_spi)) { 00151 return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); 00152 } 00153 start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); 00154 return 0; 00155 } 00156 00157 void SPI::abort_transfer() 00158 { 00159 spi_abort_asynch(&_spi); 00160 unlock_deep_sleep(); 00161 #if TRANSACTION_QUEUE_SIZE_SPI 00162 dequeue_transaction(); 00163 #endif 00164 } 00165 00166 00167 void SPI::clear_transfer_buffer() 00168 { 00169 #if TRANSACTION_QUEUE_SIZE_SPI 00170 _transaction_buffer.reset(); 00171 #endif 00172 } 00173 00174 void SPI::abort_all_transfers() 00175 { 00176 clear_transfer_buffer(); 00177 abort_transfer(); 00178 } 00179 00180 int SPI::set_dma_usage(DMAUsage usage) 00181 { 00182 if (spi_active(&_spi)) { 00183 return -1; 00184 } 00185 _usage = usage; 00186 return 0; 00187 } 00188 00189 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) 00190 { 00191 #if TRANSACTION_QUEUE_SIZE_SPI 00192 transaction_t t; 00193 00194 t.tx_buffer = const_cast<void *>(tx_buffer); 00195 t.tx_length = tx_length; 00196 t.rx_buffer = rx_buffer; 00197 t.rx_length = rx_length; 00198 t.event = event; 00199 t.callback = callback; 00200 t.width = bit_width; 00201 Transaction<SPI> transaction(this, t); 00202 if (_transaction_buffer.full()) { 00203 return -1; // the buffer is full 00204 } else { 00205 core_util_critical_section_enter(); 00206 _transaction_buffer.push(transaction); 00207 if (!spi_active(&_spi)) { 00208 dequeue_transaction(); 00209 } 00210 core_util_critical_section_exit(); 00211 return 0; 00212 } 00213 #else 00214 return -1; 00215 #endif 00216 } 00217 00218 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) 00219 { 00220 lock_deep_sleep(); 00221 _acquire(); 00222 _callback = callback; 00223 _irq.callback(&SPI::irq_handler_asynch); 00224 spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event, _usage); 00225 } 00226 00227 void SPI::lock_deep_sleep() 00228 { 00229 if (_deep_sleep_locked == false) { 00230 sleep_manager_lock_deep_sleep(); 00231 _deep_sleep_locked = true; 00232 } 00233 } 00234 00235 void SPI::unlock_deep_sleep() 00236 { 00237 if (_deep_sleep_locked == true) { 00238 sleep_manager_unlock_deep_sleep(); 00239 _deep_sleep_locked = false; 00240 } 00241 } 00242 00243 #if TRANSACTION_QUEUE_SIZE_SPI 00244 00245 void SPI::start_transaction(transaction_t *data) 00246 { 00247 start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event); 00248 } 00249 00250 void SPI::dequeue_transaction() 00251 { 00252 Transaction<SPI> t; 00253 if (_transaction_buffer.pop(t)) { 00254 SPI *obj = t.get_object(); 00255 transaction_t *data = t.get_transaction(); 00256 obj->start_transaction(data); 00257 } 00258 } 00259 00260 #endif 00261 00262 void SPI::irq_handler_asynch(void) 00263 { 00264 int event = spi_irq_handler_asynch(&_spi); 00265 if (_callback && (event & SPI_EVENT_ALL)) { 00266 unlock_deep_sleep(); 00267 _callback.call(event & SPI_EVENT_ALL); 00268 } 00269 #if TRANSACTION_QUEUE_SIZE_SPI 00270 if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) { 00271 // SPI peripheral is free (event happened), dequeue transaction 00272 dequeue_transaction(); 00273 } 00274 #endif 00275 } 00276 00277 #endif 00278 00279 } // namespace mbed 00280 00281 #endif
Generated on Tue Jul 12 2022 20:41:16 by 1.7.2