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 #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(const 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 (const 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 = const_cast<void *>(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 __disable_irq(); 00128 _transaction_buffer.push(transaction); 00129 if (!spi_active(&_spi)) { 00130 dequeue_transaction(); 00131 } 00132 __enable_irq(); 00133 return 0; 00134 } 00135 #else 00136 return -1; 00137 #endif 00138 } 00139 00140 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) 00141 { 00142 aquire(); 00143 _callback = callback; 00144 _irq.callback(&SPI::irq_handler_asynch); 00145 spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage); 00146 } 00147 00148 #if TRANSACTION_QUEUE_SIZE_SPI 00149 00150 void SPI::start_transaction(transaction_t *data) 00151 { 00152 start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event); 00153 } 00154 00155 void SPI::dequeue_transaction() 00156 { 00157 Transaction<SPI> t; 00158 if (_transaction_buffer.pop(t)) { 00159 SPI* obj = t.get_object(); 00160 transaction_t* data = t.get_transaction(); 00161 obj->start_transaction(data); 00162 } 00163 } 00164 00165 #endif 00166 00167 void SPI::irq_handler_asynch(void) 00168 { 00169 int event = spi_irq_handler_asynch(&_spi); 00170 if (_callback && (event & SPI_EVENT_ALL)) { 00171 _callback.call(event & SPI_EVENT_ALL); 00172 } 00173 #if TRANSACTION_QUEUE_SIZE_SPI 00174 if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) { 00175 // SPI peripheral is free (event happend), dequeue transaction 00176 dequeue_transaction(); 00177 } 00178 #endif 00179 } 00180 00181 #endif 00182 00183 } // namespace mbed 00184 00185 #endif
Generated on Tue Jul 12 2022 18:56:14 by
