init

Dependencies:   mbed

Committer:
Nathan Yonkee
Date:
Fri Mar 02 07:16:49 2018 -0700
Revision:
10:46a4cf51ee38
Parent:
9:d58e77ebd769
remove mbed-os

Who changed what in which revision?

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