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