mbed library sources. Supersedes mbed-src.

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

Committer:
AnnaBridge
Date:
Thu Sep 06 13:40:20 2018 +0100
Revision:
187:0387e8f68319
Parent:
184:08ed48f1de7f
Child:
188:bcfe06ba3d64
mbed-dev library. Release version 163

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
<> 149:156823d33999 44
<> 149:156823d33999 45 spi_init(&_spi, mosi, miso, sclk, ssel);
Kojto 169:e3b6fe271b81 46 _acquire();
<> 149:156823d33999 47 }
<> 149:156823d33999 48
AnnaBridge 187:0387e8f68319 49 void SPI::format(int bits, int mode)
AnnaBridge 187:0387e8f68319 50 {
<> 149:156823d33999 51 lock();
<> 149:156823d33999 52 _bits = bits;
<> 149:156823d33999 53 _mode = mode;
AnnaBridge 184:08ed48f1de7f 54 // If changing format while you are the owner then just
AnnaBridge 184:08ed48f1de7f 55 // update format, but if owner is changed then even frequency should be
Kojto 169:e3b6fe271b81 56 // updated which is done by acquire.
Kojto 169:e3b6fe271b81 57 if (_owner == this) {
Kojto 169:e3b6fe271b81 58 spi_format(&_spi, _bits, _mode, 0);
Kojto 169:e3b6fe271b81 59 } else {
Kojto 169:e3b6fe271b81 60 _acquire();
Kojto 169:e3b6fe271b81 61 }
<> 149:156823d33999 62 unlock();
<> 149:156823d33999 63 }
<> 149:156823d33999 64
AnnaBridge 187:0387e8f68319 65 void SPI::frequency(int hz)
AnnaBridge 187:0387e8f68319 66 {
<> 149:156823d33999 67 lock();
<> 149:156823d33999 68 _hz = hz;
AnnaBridge 184:08ed48f1de7f 69 // If changing format while you are the owner then just
AnnaBridge 184:08ed48f1de7f 70 // update frequency, but if owner is changed then even frequency should be
Kojto 169:e3b6fe271b81 71 // updated which is done by acquire.
Kojto 169:e3b6fe271b81 72 if (_owner == this) {
Kojto 169:e3b6fe271b81 73 spi_frequency(&_spi, _hz);
Kojto 169:e3b6fe271b81 74 } else {
Kojto 169:e3b6fe271b81 75 _acquire();
Kojto 169:e3b6fe271b81 76 }
<> 149:156823d33999 77 unlock();
<> 149:156823d33999 78 }
<> 149:156823d33999 79
AnnaBridge 187:0387e8f68319 80 SPI *SPI::_owner = NULL;
<> 149:156823d33999 81 SingletonPtr<PlatformMutex> SPI::_mutex;
<> 149:156823d33999 82
AnnaBridge 184:08ed48f1de7f 83 // ignore the fact there are multiple physical spis, and always update if it wasn't us last
AnnaBridge 187:0387e8f68319 84 void SPI::aquire()
AnnaBridge 187:0387e8f68319 85 {
<> 149:156823d33999 86 lock();
AnnaBridge 187:0387e8f68319 87 if (_owner != this) {
<> 149:156823d33999 88 spi_format(&_spi, _bits, _mode, 0);
<> 149:156823d33999 89 spi_frequency(&_spi, _hz);
<> 149:156823d33999 90 _owner = this;
<> 149:156823d33999 91 }
<> 149:156823d33999 92 unlock();
<> 149:156823d33999 93 }
<> 149:156823d33999 94
Kojto 169:e3b6fe271b81 95 // Note: Private function with no locking
AnnaBridge 187:0387e8f68319 96 void SPI::_acquire()
AnnaBridge 187:0387e8f68319 97 {
AnnaBridge 187:0387e8f68319 98 if (_owner != this) {
Kojto 169:e3b6fe271b81 99 spi_format(&_spi, _bits, _mode, 0);
Kojto 169:e3b6fe271b81 100 spi_frequency(&_spi, _hz);
Kojto 169:e3b6fe271b81 101 _owner = this;
Kojto 169:e3b6fe271b81 102 }
Kojto 169:e3b6fe271b81 103 }
Kojto 169:e3b6fe271b81 104
AnnaBridge 187:0387e8f68319 105 int SPI::write(int value)
AnnaBridge 187:0387e8f68319 106 {
<> 149:156823d33999 107 lock();
Kojto 169:e3b6fe271b81 108 _acquire();
<> 149:156823d33999 109 int ret = spi_master_write(&_spi, value);
<> 149:156823d33999 110 unlock();
<> 149:156823d33999 111 return ret;
<> 149:156823d33999 112 }
<> 149:156823d33999 113
AnnaBridge 187:0387e8f68319 114 int SPI::write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length)
AnnaBridge 187:0387e8f68319 115 {
AnnaBridge 167:e84263d55307 116 lock();
Kojto 169:e3b6fe271b81 117 _acquire();
Kojto 170:19eb464bc2be 118 int ret = spi_master_block_write(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, _write_fill);
AnnaBridge 167:e84263d55307 119 unlock();
AnnaBridge 167:e84263d55307 120 return ret;
AnnaBridge 167:e84263d55307 121 }
AnnaBridge 167:e84263d55307 122
AnnaBridge 187:0387e8f68319 123 void SPI::lock()
AnnaBridge 187:0387e8f68319 124 {
<> 149:156823d33999 125 _mutex->lock();
<> 149:156823d33999 126 }
<> 149:156823d33999 127
AnnaBridge 187:0387e8f68319 128 void SPI::unlock()
AnnaBridge 187:0387e8f68319 129 {
<> 149:156823d33999 130 _mutex->unlock();
<> 149:156823d33999 131 }
<> 149:156823d33999 132
AnnaBridge 187:0387e8f68319 133 void SPI::set_default_write_value(char data)
AnnaBridge 187:0387e8f68319 134 {
Kojto 170:19eb464bc2be 135 lock();
Kojto 170:19eb464bc2be 136 _write_fill = data;
Kojto 170:19eb464bc2be 137 unlock();
Kojto 170:19eb464bc2be 138 }
Kojto 170:19eb464bc2be 139
<> 149:156823d33999 140 #if DEVICE_SPI_ASYNCH
<> 149:156823d33999 141
AnnaBridge 187:0387e8f68319 142 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 143 {
<> 149:156823d33999 144 if (spi_active(&_spi)) {
<> 149:156823d33999 145 return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
<> 149:156823d33999 146 }
<> 149:156823d33999 147 start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
<> 149:156823d33999 148 return 0;
<> 149:156823d33999 149 }
<> 149:156823d33999 150
<> 149:156823d33999 151 void SPI::abort_transfer()
<> 149:156823d33999 152 {
<> 149:156823d33999 153 spi_abort_asynch(&_spi);
Anna Bridge 180:96ed750bd169 154 unlock_deep_sleep();
<> 149:156823d33999 155 #if TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 156 dequeue_transaction();
<> 149:156823d33999 157 #endif
<> 149:156823d33999 158 }
<> 149:156823d33999 159
<> 149:156823d33999 160
<> 149:156823d33999 161 void SPI::clear_transfer_buffer()
<> 149:156823d33999 162 {
<> 149:156823d33999 163 #if TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 164 _transaction_buffer.reset();
<> 149:156823d33999 165 #endif
<> 149:156823d33999 166 }
<> 149:156823d33999 167
<> 149:156823d33999 168 void SPI::abort_all_transfers()
<> 149:156823d33999 169 {
<> 149:156823d33999 170 clear_transfer_buffer();
<> 149:156823d33999 171 abort_transfer();
<> 149:156823d33999 172 }
<> 149:156823d33999 173
<> 149:156823d33999 174 int SPI::set_dma_usage(DMAUsage usage)
<> 149:156823d33999 175 {
<> 149:156823d33999 176 if (spi_active(&_spi)) {
<> 149:156823d33999 177 return -1;
<> 149:156823d33999 178 }
<> 149:156823d33999 179 _usage = usage;
<> 149:156823d33999 180 return 0;
<> 149:156823d33999 181 }
<> 149:156823d33999 182
AnnaBridge 187:0387e8f68319 183 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 184 {
<> 149:156823d33999 185 #if TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 186 transaction_t t;
<> 149:156823d33999 187
<> 149:156823d33999 188 t.tx_buffer = const_cast<void *>(tx_buffer);
<> 149:156823d33999 189 t.tx_length = tx_length;
<> 149:156823d33999 190 t.rx_buffer = rx_buffer;
<> 149:156823d33999 191 t.rx_length = rx_length;
<> 149:156823d33999 192 t.event = event;
<> 149:156823d33999 193 t.callback = callback;
<> 149:156823d33999 194 t.width = bit_width;
<> 149:156823d33999 195 Transaction<SPI> transaction(this, t);
<> 149:156823d33999 196 if (_transaction_buffer.full()) {
<> 149:156823d33999 197 return -1; // the buffer is full
<> 149:156823d33999 198 } else {
<> 149:156823d33999 199 core_util_critical_section_enter();
<> 149:156823d33999 200 _transaction_buffer.push(transaction);
<> 149:156823d33999 201 if (!spi_active(&_spi)) {
<> 149:156823d33999 202 dequeue_transaction();
<> 149:156823d33999 203 }
<> 149:156823d33999 204 core_util_critical_section_exit();
<> 149:156823d33999 205 return 0;
<> 149:156823d33999 206 }
<> 149:156823d33999 207 #else
<> 149:156823d33999 208 return -1;
<> 149:156823d33999 209 #endif
<> 149:156823d33999 210 }
<> 149:156823d33999 211
AnnaBridge 187:0387e8f68319 212 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 213 {
Anna Bridge 180:96ed750bd169 214 lock_deep_sleep();
Kojto 169:e3b6fe271b81 215 _acquire();
<> 149:156823d33999 216 _callback = callback;
<> 149:156823d33999 217 _irq.callback(&SPI::irq_handler_asynch);
AnnaBridge 187:0387e8f68319 218 spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event, _usage);
<> 149:156823d33999 219 }
<> 149:156823d33999 220
Anna Bridge 180:96ed750bd169 221 void SPI::lock_deep_sleep()
Anna Bridge 180:96ed750bd169 222 {
Anna Bridge 180:96ed750bd169 223 if (_deep_sleep_locked == false) {
Anna Bridge 180:96ed750bd169 224 sleep_manager_lock_deep_sleep();
Anna Bridge 180:96ed750bd169 225 _deep_sleep_locked = true;
Anna Bridge 180:96ed750bd169 226 }
Anna Bridge 180:96ed750bd169 227 }
Anna Bridge 180:96ed750bd169 228
Anna Bridge 180:96ed750bd169 229 void SPI::unlock_deep_sleep()
Anna Bridge 180:96ed750bd169 230 {
Anna Bridge 180:96ed750bd169 231 if (_deep_sleep_locked == true) {
Anna Bridge 180:96ed750bd169 232 sleep_manager_unlock_deep_sleep();
Anna Bridge 180:96ed750bd169 233 _deep_sleep_locked = false;
Anna Bridge 180:96ed750bd169 234 }
Anna Bridge 180:96ed750bd169 235 }
Anna Bridge 180:96ed750bd169 236
<> 149:156823d33999 237 #if TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 238
<> 149:156823d33999 239 void SPI::start_transaction(transaction_t *data)
<> 149:156823d33999 240 {
<> 149:156823d33999 241 start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event);
<> 149:156823d33999 242 }
<> 149:156823d33999 243
<> 149:156823d33999 244 void SPI::dequeue_transaction()
<> 149:156823d33999 245 {
<> 149:156823d33999 246 Transaction<SPI> t;
<> 149:156823d33999 247 if (_transaction_buffer.pop(t)) {
AnnaBridge 187:0387e8f68319 248 SPI *obj = t.get_object();
AnnaBridge 187:0387e8f68319 249 transaction_t *data = t.get_transaction();
<> 149:156823d33999 250 obj->start_transaction(data);
<> 149:156823d33999 251 }
<> 149:156823d33999 252 }
<> 149:156823d33999 253
<> 149:156823d33999 254 #endif
<> 149:156823d33999 255
<> 149:156823d33999 256 void SPI::irq_handler_asynch(void)
<> 149:156823d33999 257 {
<> 149:156823d33999 258 int event = spi_irq_handler_asynch(&_spi);
<> 149:156823d33999 259 if (_callback && (event & SPI_EVENT_ALL)) {
Anna Bridge 180:96ed750bd169 260 unlock_deep_sleep();
<> 149:156823d33999 261 _callback.call(event & SPI_EVENT_ALL);
<> 149:156823d33999 262 }
<> 149:156823d33999 263 #if TRANSACTION_QUEUE_SIZE_SPI
<> 149:156823d33999 264 if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) {
AnnaBridge 184:08ed48f1de7f 265 // SPI peripheral is free (event happened), dequeue transaction
<> 149:156823d33999 266 dequeue_transaction();
<> 149:156823d33999 267 }
<> 149:156823d33999 268 #endif
<> 149:156823d33999 269 }
<> 149:156823d33999 270
<> 149:156823d33999 271 #endif
<> 149:156823d33999 272
<> 149:156823d33999 273 } // namespace mbed
<> 149:156823d33999 274
<> 149:156823d33999 275 #endif