mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Thu Nov 08 11:46:34 2018 +0000
Revision:
188:bcfe06ba3d64
Parent:
187:0387e8f68319
Child:
189:f392fc9709a3
mbed-dev library. Release version 164

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 149:156823d33999 1 /* mbed Microcontroller Library
<> 149:156823d33999 2 * Copyright (c) 2006-2013 ARM Limited
<> 149:156823d33999 3 *
<> 149:156823d33999 4 * Licensed under the Apache License, Version 2.0 (the "License");
<> 149:156823d33999 5 * you may not use this file except in compliance with the License.
<> 149:156823d33999 6 * You may obtain a copy of the License at
<> 149:156823d33999 7 *
<> 149:156823d33999 8 * http://www.apache.org/licenses/LICENSE-2.0
<> 149:156823d33999 9 *
<> 149:156823d33999 10 * Unless required by applicable law or agreed to in writing, software
<> 149:156823d33999 11 * distributed under the License is distributed on an "AS IS" BASIS,
<> 149:156823d33999 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<> 149:156823d33999 13 * See the License for the specific language governing permissions and
<> 149:156823d33999 14 * limitations under the License.
<> 149:156823d33999 15 */
<> 149:156823d33999 16 #include "drivers/SPI.h"
<> 160:d5399cc887bb 17 #include "platform/mbed_critical.h"
<> 149:156823d33999 18
AnnaBridge 174:b96e65c34a4d 19 #if DEVICE_SPI_ASYNCH
AnnaBridge 184:08ed48f1de7f 20 #include "platform/mbed_power_mgmt.h"
AnnaBridge 174:b96e65c34a4d 21 #endif
AnnaBridge 174:b96e65c34a4d 22
<> 149:156823d33999 23 #if DEVICE_SPI
<> 149:156823d33999 24
<> 149:156823d33999 25 namespace mbed {
<> 149:156823d33999 26
<> 149:156823d33999 27 #if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 28 CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> SPI::_transaction_buffer;
<> 149:156823d33999 29 #endif
<> 149:156823d33999 30
<> 149:156823d33999 31 SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) :
AnnaBridge 187:0387e8f68319 32 _spi(),
<> 149:156823d33999 33 #if DEVICE_SPI_ASYNCH
AnnaBridge 187:0387e8f68319 34 _irq(this),
AnnaBridge 187:0387e8f68319 35 _usage(DMA_USAGE_NEVER),
AnnaBridge 187:0387e8f68319 36 _deep_sleep_locked(false),
<> 149:156823d33999 37 #endif
AnnaBridge 187:0387e8f68319 38 _bits(8),
AnnaBridge 187:0387e8f68319 39 _mode(0),
AnnaBridge 187:0387e8f68319 40 _hz(1000000),
AnnaBridge 187:0387e8f68319 41 _write_fill(SPI_FILL_CHAR)
AnnaBridge 187:0387e8f68319 42 {
<> 149:156823d33999 43 // No lock needed in the constructor
AnnaBridge 188:bcfe06ba3d64 44 spi_init(&_spi, mosi, miso, sclk, ssel);
AnnaBridge 188:bcfe06ba3d64 45 }
<> 149:156823d33999 46
AnnaBridge 188:bcfe06ba3d64 47 SPI::~SPI()
AnnaBridge 188:bcfe06ba3d64 48 {
AnnaBridge 188:bcfe06ba3d64 49 if (_owner == this) {
AnnaBridge 188:bcfe06ba3d64 50 _owner = NULL;
AnnaBridge 188:bcfe06ba3d64 51 }
<> 149:156823d33999 52 }
<> 149:156823d33999 53
AnnaBridge 187:0387e8f68319 54 void SPI::format(int bits, int mode)
AnnaBridge 187:0387e8f68319 55 {
<> 149:156823d33999 56 lock();
<> 149:156823d33999 57 _bits = bits;
<> 149:156823d33999 58 _mode = mode;
AnnaBridge 184:08ed48f1de7f 59 // If changing format while you are the owner then just
AnnaBridge 184:08ed48f1de7f 60 // update format, but if owner is changed then even frequency should be
Kojto 169:e3b6fe271b81 61 // updated which is done by acquire.
Kojto 169:e3b6fe271b81 62 if (_owner == this) {
Kojto 169:e3b6fe271b81 63 spi_format(&_spi, _bits, _mode, 0);
Kojto 169:e3b6fe271b81 64 } else {
Kojto 169:e3b6fe271b81 65 _acquire();
Kojto 169:e3b6fe271b81 66 }
<> 149:156823d33999 67 unlock();
<> 149:156823d33999 68 }
<> 149:156823d33999 69
AnnaBridge 187:0387e8f68319 70 void SPI::frequency(int hz)
AnnaBridge 187:0387e8f68319 71 {
<> 149:156823d33999 72 lock();
<> 149:156823d33999 73 _hz = hz;
AnnaBridge 184:08ed48f1de7f 74 // If changing format while you are the owner then just
AnnaBridge 184:08ed48f1de7f 75 // update frequency, but if owner is changed then even frequency should be
Kojto 169:e3b6fe271b81 76 // updated which is done by acquire.
Kojto 169:e3b6fe271b81 77 if (_owner == this) {
Kojto 169:e3b6fe271b81 78 spi_frequency(&_spi, _hz);
Kojto 169:e3b6fe271b81 79 } else {
Kojto 169:e3b6fe271b81 80 _acquire();
Kojto 169:e3b6fe271b81 81 }
<> 149:156823d33999 82 unlock();
<> 149:156823d33999 83 }
<> 149:156823d33999 84
AnnaBridge 187:0387e8f68319 85 SPI *SPI::_owner = NULL;
<> 149:156823d33999 86 SingletonPtr<PlatformMutex> SPI::_mutex;
<> 149:156823d33999 87
AnnaBridge 184:08ed48f1de7f 88 // ignore the fact there are multiple physical spis, and always update if it wasn't us last
AnnaBridge 187:0387e8f68319 89 void SPI::aquire()
AnnaBridge 187:0387e8f68319 90 {
<> 149:156823d33999 91 lock();
AnnaBridge 187:0387e8f68319 92 if (_owner != this) {
<> 149:156823d33999 93 spi_format(&_spi, _bits, _mode, 0);
<> 149:156823d33999 94 spi_frequency(&_spi, _hz);
<> 149:156823d33999 95 _owner = this;
<> 149:156823d33999 96 }
<> 149:156823d33999 97 unlock();
<> 149:156823d33999 98 }
<> 149:156823d33999 99
Kojto 169:e3b6fe271b81 100 // Note: Private function with no locking
AnnaBridge 187:0387e8f68319 101 void SPI::_acquire()
AnnaBridge 187:0387e8f68319 102 {
AnnaBridge 187:0387e8f68319 103 if (_owner != this) {
Kojto 169:e3b6fe271b81 104 spi_format(&_spi, _bits, _mode, 0);
Kojto 169:e3b6fe271b81 105 spi_frequency(&_spi, _hz);
Kojto 169:e3b6fe271b81 106 _owner = this;
Kojto 169:e3b6fe271b81 107 }
Kojto 169:e3b6fe271b81 108 }
Kojto 169:e3b6fe271b81 109
AnnaBridge 187:0387e8f68319 110 int SPI::write(int value)
AnnaBridge 187:0387e8f68319 111 {
<> 149:156823d33999 112 lock();
Kojto 169:e3b6fe271b81 113 _acquire();
<> 149:156823d33999 114 int ret = spi_master_write(&_spi, value);
<> 149:156823d33999 115 unlock();
<> 149:156823d33999 116 return ret;
<> 149:156823d33999 117 }
<> 149:156823d33999 118
AnnaBridge 187:0387e8f68319 119 int SPI::write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length)
AnnaBridge 187:0387e8f68319 120 {
AnnaBridge 167:e84263d55307 121 lock();
Kojto 169:e3b6fe271b81 122 _acquire();
Kojto 170:19eb464bc2be 123 int ret = spi_master_block_write(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, _write_fill);
AnnaBridge 167:e84263d55307 124 unlock();
AnnaBridge 167:e84263d55307 125 return ret;
AnnaBridge 167:e84263d55307 126 }
AnnaBridge 167:e84263d55307 127
AnnaBridge 187:0387e8f68319 128 void SPI::lock()
AnnaBridge 187:0387e8f68319 129 {
<> 149:156823d33999 130 _mutex->lock();
<> 149:156823d33999 131 }
<> 149:156823d33999 132
AnnaBridge 187:0387e8f68319 133 void SPI::unlock()
AnnaBridge 187:0387e8f68319 134 {
<> 149:156823d33999 135 _mutex->unlock();
<> 149:156823d33999 136 }
<> 149:156823d33999 137
AnnaBridge 187:0387e8f68319 138 void SPI::set_default_write_value(char data)
AnnaBridge 187:0387e8f68319 139 {
Kojto 170:19eb464bc2be 140 lock();
Kojto 170:19eb464bc2be 141 _write_fill = data;
Kojto 170:19eb464bc2be 142 unlock();
Kojto 170:19eb464bc2be 143 }
Kojto 170:19eb464bc2be 144
<> 149:156823d33999 145 #if DEVICE_SPI_ASYNCH
<> 149:156823d33999 146
AnnaBridge 187:0387e8f68319 147 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)
<> 149:156823d33999 148 {
<> 149:156823d33999 149 if (spi_active(&_spi)) {
<> 149:156823d33999 150 return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
<> 149:156823d33999 151 }
<> 149:156823d33999 152 start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
<> 149:156823d33999 153 return 0;
<> 149:156823d33999 154 }
<> 149:156823d33999 155
<> 149:156823d33999 156 void SPI::abort_transfer()
<> 149:156823d33999 157 {
<> 149:156823d33999 158 spi_abort_asynch(&_spi);
Anna Bridge 180:96ed750bd169 159 unlock_deep_sleep();
<> 149:156823d33999 160 #if TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 161 dequeue_transaction();
<> 149:156823d33999 162 #endif
<> 149:156823d33999 163 }
<> 149:156823d33999 164
<> 149:156823d33999 165
<> 149:156823d33999 166 void SPI::clear_transfer_buffer()
<> 149:156823d33999 167 {
<> 149:156823d33999 168 #if TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 169 _transaction_buffer.reset();
<> 149:156823d33999 170 #endif
<> 149:156823d33999 171 }
<> 149:156823d33999 172
<> 149:156823d33999 173 void SPI::abort_all_transfers()
<> 149:156823d33999 174 {
<> 149:156823d33999 175 clear_transfer_buffer();
<> 149:156823d33999 176 abort_transfer();
<> 149:156823d33999 177 }
<> 149:156823d33999 178
<> 149:156823d33999 179 int SPI::set_dma_usage(DMAUsage usage)
<> 149:156823d33999 180 {
<> 149:156823d33999 181 if (spi_active(&_spi)) {
<> 149:156823d33999 182 return -1;
<> 149:156823d33999 183 }
<> 149:156823d33999 184 _usage = usage;
<> 149:156823d33999 185 return 0;
<> 149:156823d33999 186 }
<> 149:156823d33999 187
AnnaBridge 187:0387e8f68319 188 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)
<> 149:156823d33999 189 {
<> 149:156823d33999 190 #if TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 191 transaction_t t;
<> 149:156823d33999 192
<> 149:156823d33999 193 t.tx_buffer = const_cast<void *>(tx_buffer);
<> 149:156823d33999 194 t.tx_length = tx_length;
<> 149:156823d33999 195 t.rx_buffer = rx_buffer;
<> 149:156823d33999 196 t.rx_length = rx_length;
<> 149:156823d33999 197 t.event = event;
<> 149:156823d33999 198 t.callback = callback;
<> 149:156823d33999 199 t.width = bit_width;
<> 149:156823d33999 200 Transaction<SPI> transaction(this, t);
<> 149:156823d33999 201 if (_transaction_buffer.full()) {
<> 149:156823d33999 202 return -1; // the buffer is full
<> 149:156823d33999 203 } else {
<> 149:156823d33999 204 core_util_critical_section_enter();
<> 149:156823d33999 205 _transaction_buffer.push(transaction);
<> 149:156823d33999 206 if (!spi_active(&_spi)) {
<> 149:156823d33999 207 dequeue_transaction();
<> 149:156823d33999 208 }
<> 149:156823d33999 209 core_util_critical_section_exit();
<> 149:156823d33999 210 return 0;
<> 149:156823d33999 211 }
<> 149:156823d33999 212 #else
<> 149:156823d33999 213 return -1;
<> 149:156823d33999 214 #endif
<> 149:156823d33999 215 }
<> 149:156823d33999 216
AnnaBridge 187:0387e8f68319 217 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)
<> 149:156823d33999 218 {
Anna Bridge 180:96ed750bd169 219 lock_deep_sleep();
Kojto 169:e3b6fe271b81 220 _acquire();
<> 149:156823d33999 221 _callback = callback;
<> 149:156823d33999 222 _irq.callback(&SPI::irq_handler_asynch);
AnnaBridge 187:0387e8f68319 223 spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event, _usage);
<> 149:156823d33999 224 }
<> 149:156823d33999 225
Anna Bridge 180:96ed750bd169 226 void SPI::lock_deep_sleep()
Anna Bridge 180:96ed750bd169 227 {
Anna Bridge 180:96ed750bd169 228 if (_deep_sleep_locked == false) {
Anna Bridge 180:96ed750bd169 229 sleep_manager_lock_deep_sleep();
Anna Bridge 180:96ed750bd169 230 _deep_sleep_locked = true;
Anna Bridge 180:96ed750bd169 231 }
Anna Bridge 180:96ed750bd169 232 }
Anna Bridge 180:96ed750bd169 233
Anna Bridge 180:96ed750bd169 234 void SPI::unlock_deep_sleep()
Anna Bridge 180:96ed750bd169 235 {
Anna Bridge 180:96ed750bd169 236 if (_deep_sleep_locked == true) {
Anna Bridge 180:96ed750bd169 237 sleep_manager_unlock_deep_sleep();
Anna Bridge 180:96ed750bd169 238 _deep_sleep_locked = false;
Anna Bridge 180:96ed750bd169 239 }
Anna Bridge 180:96ed750bd169 240 }
Anna Bridge 180:96ed750bd169 241
<> 149:156823d33999 242 #if TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 243
<> 149:156823d33999 244 void SPI::start_transaction(transaction_t *data)
<> 149:156823d33999 245 {
<> 149:156823d33999 246 start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event);
<> 149:156823d33999 247 }
<> 149:156823d33999 248
<> 149:156823d33999 249 void SPI::dequeue_transaction()
<> 149:156823d33999 250 {
<> 149:156823d33999 251 Transaction<SPI> t;
<> 149:156823d33999 252 if (_transaction_buffer.pop(t)) {
AnnaBridge 187:0387e8f68319 253 SPI *obj = t.get_object();
AnnaBridge 187:0387e8f68319 254 transaction_t *data = t.get_transaction();
<> 149:156823d33999 255 obj->start_transaction(data);
<> 149:156823d33999 256 }
<> 149:156823d33999 257 }
<> 149:156823d33999 258
<> 149:156823d33999 259 #endif
<> 149:156823d33999 260
<> 149:156823d33999 261 void SPI::irq_handler_asynch(void)
<> 149:156823d33999 262 {
<> 149:156823d33999 263 int event = spi_irq_handler_asynch(&_spi);
<> 149:156823d33999 264 if (_callback && (event & SPI_EVENT_ALL)) {
Anna Bridge 180:96ed750bd169 265 unlock_deep_sleep();
<> 149:156823d33999 266 _callback.call(event & SPI_EVENT_ALL);
<> 149:156823d33999 267 }
<> 149:156823d33999 268 #if TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 269 if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) {
AnnaBridge 184:08ed48f1de7f 270 // SPI peripheral is free (event happened), dequeue transaction
<> 149:156823d33999 271 dequeue_transaction();
<> 149:156823d33999 272 }
<> 149:156823d33999 273 #endif
<> 149:156823d33999 274 }
<> 149:156823d33999 275
<> 149:156823d33999 276 #endif
<> 149:156823d33999 277
<> 149:156823d33999 278 } // namespace mbed
<> 149:156823d33999 279
<> 149:156823d33999 280 #endif