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 TUKS-COURSE-TIMER 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/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 void SPI::lock() { 00082 _mutex->lock(); 00083 } 00084 00085 void SPI::unlock() { 00086 _mutex->unlock(); 00087 } 00088 00089 #if DEVICE_SPI_ASYNCH 00090 00091 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) 00092 { 00093 if (spi_active(&_spi)) { 00094 return queue_transfer (tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); 00095 } 00096 start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); 00097 return 0; 00098 } 00099 00100 void SPI::abort_transfer() 00101 { 00102 spi_abort_asynch(&_spi); 00103 #if TRANSACTION_QUEUE_SIZE_SPI 00104 dequeue_transaction(); 00105 #endif 00106 } 00107 00108 00109 void SPI::clear_transfer_buffer() 00110 { 00111 #if TRANSACTION_QUEUE_SIZE_SPI 00112 _transaction_buffer.reset(); 00113 #endif 00114 } 00115 00116 void SPI::abort_all_transfers() 00117 { 00118 clear_transfer_buffer(); 00119 abort_transfer(); 00120 } 00121 00122 int SPI::set_dma_usage(DMAUsage usage) 00123 { 00124 if (spi_active(&_spi)) { 00125 return -1; 00126 } 00127 _usage = usage; 00128 return 0; 00129 } 00130 00131 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) 00132 { 00133 #if TRANSACTION_QUEUE_SIZE_SPI 00134 transaction_t t; 00135 00136 t.tx_buffer = const_cast<void *>(tx_buffer); 00137 t.tx_length = tx_length; 00138 t.rx_buffer = rx_buffer; 00139 t.rx_length = rx_length; 00140 t.event = event; 00141 t.callback = callback; 00142 t.width = bit_width; 00143 Transaction<SPI> transaction(this, t); 00144 if (_transaction_buffer.full()) { 00145 return -1; // the buffer is full 00146 } else { 00147 core_util_critical_section_enter(); 00148 _transaction_buffer.push(transaction); 00149 if (!spi_active(&_spi)) { 00150 dequeue_transaction(); 00151 } 00152 core_util_critical_section_exit(); 00153 return 0; 00154 } 00155 #else 00156 return -1; 00157 #endif 00158 } 00159 00160 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) 00161 { 00162 aquire(); 00163 _callback = callback; 00164 _irq.callback(&SPI::irq_handler_asynch); 00165 spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage); 00166 } 00167 00168 #if TRANSACTION_QUEUE_SIZE_SPI 00169 00170 void SPI::start_transaction(transaction_t *data) 00171 { 00172 start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event); 00173 } 00174 00175 void SPI::dequeue_transaction() 00176 { 00177 Transaction<SPI> t; 00178 if (_transaction_buffer.pop(t)) { 00179 SPI* obj = t.get_object(); 00180 transaction_t* data = t.get_transaction(); 00181 obj->start_transaction(data); 00182 } 00183 } 00184 00185 #endif 00186 00187 void SPI::irq_handler_asynch(void) 00188 { 00189 int event = spi_irq_handler_asynch(&_spi); 00190 if (_callback && (event & SPI_EVENT_ALL)) { 00191 _callback.call(event & SPI_EVENT_ALL); 00192 } 00193 #if TRANSACTION_QUEUE_SIZE_SPI 00194 if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) { 00195 // SPI peripheral is free (event happend), dequeue transaction 00196 dequeue_transaction(); 00197 } 00198 #endif 00199 } 00200 00201 #endif 00202 00203 } // namespace mbed 00204 00205 #endif
Generated on Tue Jul 12 2022 17:38:48 by
