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 "SPI.h" 00017 00018 // for 100F6 not implemented (N.S.) 00019 #undef DEVICE_SPI_ASYNCH 00020 00021 00022 #if DEVICE_SPI 00023 00024 namespace mbed { 00025 00026 #if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI 00027 CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> SPI::_transaction_buffer; 00028 #endif 00029 00030 SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) : 00031 _spi(), 00032 #if DEVICE_SPI_ASYNCH 00033 _irq(this), 00034 _usage(DMA_USAGE_NEVER), 00035 #endif 00036 _bits(8), 00037 _mode(0), 00038 _hz(1000000) { 00039 spi_init(&_spi, mosi, miso, sclk, ssel); 00040 spi_format(&_spi, _bits, _mode, 0); 00041 spi_frequency(&_spi, _hz); 00042 } 00043 00044 void SPI::format(int bits, int mode) { 00045 _bits = bits; 00046 _mode = mode; 00047 SPI::_owner = NULL; // Not that elegant, but works. rmeyer 00048 aquire(); 00049 } 00050 00051 void SPI::frequency(int hz) { 00052 _hz = hz; 00053 SPI::_owner = NULL; // Not that elegant, but works. rmeyer 00054 aquire(); 00055 } 00056 00057 SPI* SPI::_owner = NULL; 00058 00059 // ignore the fact there are multiple physical spis, and always update if it wasnt us last 00060 void SPI::aquire() { 00061 if (_owner != this) { 00062 spi_format(&_spi, _bits, _mode, 0); 00063 spi_frequency(&_spi, _hz); 00064 _owner = this; 00065 } 00066 } 00067 00068 int SPI::write(int value) { 00069 aquire(); 00070 return spi_master_write(&_spi, value); 00071 } 00072 00073 #if DEVICE_SPI_ASYNCH 00074 00075 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) 00076 { 00077 if (spi_active(&_spi)) { 00078 return queue_transfer (tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); 00079 } 00080 start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); 00081 return 0; 00082 } 00083 00084 void SPI::abort_transfer() 00085 { 00086 spi_abort_asynch(&_spi); 00087 #if TRANSACTION_QUEUE_SIZE_SPI 00088 dequeue_transaction(); 00089 #endif 00090 } 00091 00092 00093 void SPI::clear_transfer_buffer() 00094 { 00095 #if TRANSACTION_QUEUE_SIZE_SPI 00096 _transaction_buffer.reset(); 00097 #endif 00098 } 00099 00100 void SPI::abort_all_transfers() 00101 { 00102 clear_transfer_buffer(); 00103 abort_transfer(); 00104 } 00105 00106 int SPI::set_dma_usage(DMAUsage usage) 00107 { 00108 if (spi_active(&_spi)) { 00109 return -1; 00110 } 00111 _usage = usage; 00112 return 0; 00113 } 00114 00115 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) 00116 { 00117 #if TRANSACTION_QUEUE_SIZE_SPI 00118 transaction_t t; 00119 00120 t.tx_buffer = const_cast<void *>(tx_buffer); 00121 t.tx_length = tx_length; 00122 t.rx_buffer = rx_buffer; 00123 t.rx_length = rx_length; 00124 t.event = event; 00125 t.callback = callback; 00126 t.width = bit_width; 00127 Transaction<SPI> transaction(this, t); 00128 if (_transaction_buffer.full()) { 00129 return -1; // the buffer is full 00130 } else { 00131 _transaction_buffer.push(transaction); 00132 return 0; 00133 } 00134 #else 00135 return -1; 00136 #endif 00137 } 00138 00139 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) 00140 { 00141 aquire(); 00142 _callback = callback; 00143 _irq.callback(&SPI::irq_handler_asynch); 00144 spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage); 00145 } 00146 00147 #if TRANSACTION_QUEUE_SIZE_SPI 00148 00149 void SPI::start_transaction(transaction_t *data) 00150 { 00151 start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event); 00152 } 00153 00154 void SPI::dequeue_transaction() 00155 { 00156 Transaction<SPI> t; 00157 if (_transaction_buffer.pop(t)) { 00158 SPI* obj = t.get_object(); 00159 transaction_t* data = t.get_transaction(); 00160 obj->start_transaction(data); 00161 } 00162 } 00163 00164 #endif 00165 00166 void SPI::irq_handler_asynch(void) 00167 { 00168 int event = spi_irq_handler_asynch(&_spi); 00169 if (_callback && (event & SPI_EVENT_ALL)) { 00170 _callback.call(event & SPI_EVENT_ALL); 00171 } 00172 #if TRANSACTION_QUEUE_SIZE_SPI 00173 if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) { 00174 // SPI peripheral is free (event happend), dequeue transaction 00175 dequeue_transaction(); 00176 } 00177 #endif 00178 } 00179 00180 #endif 00181 00182 } // namespace mbed 00183 00184 #endif
Generated on Wed Jul 13 2022 04:55:01 by
1.7.2
