This fork captures the mbed lib v125 for ease of integration into older projects.

Fork of mbed-dev by mbed official

Committer:
apluscw
Date:
Fri Jul 20 21:24:42 2018 +0000
Revision:
187:92cbb9eec47b
Mbed library with source code from mbed lib v125. Posted to ease integration with some older projects.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
apluscw 187:92cbb9eec47b 1 /* mbed Microcontroller Library
apluscw 187:92cbb9eec47b 2 * Copyright (c) 2006-2013 ARM Limited
apluscw 187:92cbb9eec47b 3 *
apluscw 187:92cbb9eec47b 4 * Licensed under the Apache License, Version 2.0 (the "License");
apluscw 187:92cbb9eec47b 5 * you may not use this file except in compliance with the License.
apluscw 187:92cbb9eec47b 6 * You may obtain a copy of the License at
apluscw 187:92cbb9eec47b 7 *
apluscw 187:92cbb9eec47b 8 * http://www.apache.org/licenses/LICENSE-2.0
apluscw 187:92cbb9eec47b 9 *
apluscw 187:92cbb9eec47b 10 * Unless required by applicable law or agreed to in writing, software
apluscw 187:92cbb9eec47b 11 * distributed under the License is distributed on an "AS IS" BASIS,
apluscw 187:92cbb9eec47b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
apluscw 187:92cbb9eec47b 13 * See the License for the specific language governing permissions and
apluscw 187:92cbb9eec47b 14 * limitations under the License.
apluscw 187:92cbb9eec47b 15 */
apluscw 187:92cbb9eec47b 16 #include "SPI.h"
apluscw 187:92cbb9eec47b 17 #include "critical.h"
apluscw 187:92cbb9eec47b 18
apluscw 187:92cbb9eec47b 19 #if DEVICE_SPI
apluscw 187:92cbb9eec47b 20
apluscw 187:92cbb9eec47b 21 namespace mbed {
apluscw 187:92cbb9eec47b 22
apluscw 187:92cbb9eec47b 23 #if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI
apluscw 187:92cbb9eec47b 24 CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> SPI::_transaction_buffer;
apluscw 187:92cbb9eec47b 25 #endif
apluscw 187:92cbb9eec47b 26
apluscw 187:92cbb9eec47b 27 SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) :
apluscw 187:92cbb9eec47b 28 _spi(),
apluscw 187:92cbb9eec47b 29 #if DEVICE_SPI_ASYNCH
apluscw 187:92cbb9eec47b 30 _irq(this),
apluscw 187:92cbb9eec47b 31 _usage(DMA_USAGE_NEVER),
apluscw 187:92cbb9eec47b 32 #endif
apluscw 187:92cbb9eec47b 33 _bits(8),
apluscw 187:92cbb9eec47b 34 _mode(0),
apluscw 187:92cbb9eec47b 35 _hz(1000000) {
apluscw 187:92cbb9eec47b 36 // No lock needed in the constructor
apluscw 187:92cbb9eec47b 37
apluscw 187:92cbb9eec47b 38 spi_init(&_spi, mosi, miso, sclk, ssel);
apluscw 187:92cbb9eec47b 39 aquire();
apluscw 187:92cbb9eec47b 40 }
apluscw 187:92cbb9eec47b 41
apluscw 187:92cbb9eec47b 42 void SPI::format(int bits, int mode) {
apluscw 187:92cbb9eec47b 43 lock();
apluscw 187:92cbb9eec47b 44 _bits = bits;
apluscw 187:92cbb9eec47b 45 _mode = mode;
apluscw 187:92cbb9eec47b 46 SPI::_owner = NULL; // Not that elegant, but works. rmeyer
apluscw 187:92cbb9eec47b 47 aquire();
apluscw 187:92cbb9eec47b 48 unlock();
apluscw 187:92cbb9eec47b 49 }
apluscw 187:92cbb9eec47b 50
apluscw 187:92cbb9eec47b 51 void SPI::frequency(int hz) {
apluscw 187:92cbb9eec47b 52 lock();
apluscw 187:92cbb9eec47b 53 _hz = hz;
apluscw 187:92cbb9eec47b 54 SPI::_owner = NULL; // Not that elegant, but works. rmeyer
apluscw 187:92cbb9eec47b 55 aquire();
apluscw 187:92cbb9eec47b 56 unlock();
apluscw 187:92cbb9eec47b 57 }
apluscw 187:92cbb9eec47b 58
apluscw 187:92cbb9eec47b 59 SPI* SPI::_owner = NULL;
apluscw 187:92cbb9eec47b 60 SingletonPtr<PlatformMutex> SPI::_mutex;
apluscw 187:92cbb9eec47b 61
apluscw 187:92cbb9eec47b 62 // ignore the fact there are multiple physical spis, and always update if it wasnt us last
apluscw 187:92cbb9eec47b 63 void SPI::aquire() {
apluscw 187:92cbb9eec47b 64 lock();
apluscw 187:92cbb9eec47b 65 if (_owner != this) {
apluscw 187:92cbb9eec47b 66 spi_format(&_spi, _bits, _mode, 0);
apluscw 187:92cbb9eec47b 67 spi_frequency(&_spi, _hz);
apluscw 187:92cbb9eec47b 68 _owner = this;
apluscw 187:92cbb9eec47b 69 }
apluscw 187:92cbb9eec47b 70 unlock();
apluscw 187:92cbb9eec47b 71 }
apluscw 187:92cbb9eec47b 72
apluscw 187:92cbb9eec47b 73 int SPI::write(int value) {
apluscw 187:92cbb9eec47b 74 lock();
apluscw 187:92cbb9eec47b 75 aquire();
apluscw 187:92cbb9eec47b 76 int ret = spi_master_write(&_spi, value);
apluscw 187:92cbb9eec47b 77 unlock();
apluscw 187:92cbb9eec47b 78 return ret;
apluscw 187:92cbb9eec47b 79 }
apluscw 187:92cbb9eec47b 80
apluscw 187:92cbb9eec47b 81 void SPI::lock() {
apluscw 187:92cbb9eec47b 82 _mutex->lock();
apluscw 187:92cbb9eec47b 83 }
apluscw 187:92cbb9eec47b 84
apluscw 187:92cbb9eec47b 85 void SPI::unlock() {
apluscw 187:92cbb9eec47b 86 _mutex->unlock();
apluscw 187:92cbb9eec47b 87 }
apluscw 187:92cbb9eec47b 88
apluscw 187:92cbb9eec47b 89 #if DEVICE_SPI_ASYNCH
apluscw 187:92cbb9eec47b 90
apluscw 187:92cbb9eec47b 91 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)
apluscw 187:92cbb9eec47b 92 {
apluscw 187:92cbb9eec47b 93 if (spi_active(&_spi)) {
apluscw 187:92cbb9eec47b 94 return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
apluscw 187:92cbb9eec47b 95 }
apluscw 187:92cbb9eec47b 96 start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
apluscw 187:92cbb9eec47b 97 return 0;
apluscw 187:92cbb9eec47b 98 }
apluscw 187:92cbb9eec47b 99
apluscw 187:92cbb9eec47b 100 void SPI::abort_transfer()
apluscw 187:92cbb9eec47b 101 {
apluscw 187:92cbb9eec47b 102 spi_abort_asynch(&_spi);
apluscw 187:92cbb9eec47b 103 #if TRANSACTION_QUEUE_SIZE_SPI
apluscw 187:92cbb9eec47b 104 dequeue_transaction();
apluscw 187:92cbb9eec47b 105 #endif
apluscw 187:92cbb9eec47b 106 }
apluscw 187:92cbb9eec47b 107
apluscw 187:92cbb9eec47b 108
apluscw 187:92cbb9eec47b 109 void SPI::clear_transfer_buffer()
apluscw 187:92cbb9eec47b 110 {
apluscw 187:92cbb9eec47b 111 #if TRANSACTION_QUEUE_SIZE_SPI
apluscw 187:92cbb9eec47b 112 _transaction_buffer.reset();
apluscw 187:92cbb9eec47b 113 #endif
apluscw 187:92cbb9eec47b 114 }
apluscw 187:92cbb9eec47b 115
apluscw 187:92cbb9eec47b 116 void SPI::abort_all_transfers()
apluscw 187:92cbb9eec47b 117 {
apluscw 187:92cbb9eec47b 118 clear_transfer_buffer();
apluscw 187:92cbb9eec47b 119 abort_transfer();
apluscw 187:92cbb9eec47b 120 }
apluscw 187:92cbb9eec47b 121
apluscw 187:92cbb9eec47b 122 int SPI::set_dma_usage(DMAUsage usage)
apluscw 187:92cbb9eec47b 123 {
apluscw 187:92cbb9eec47b 124 if (spi_active(&_spi)) {
apluscw 187:92cbb9eec47b 125 return -1;
apluscw 187:92cbb9eec47b 126 }
apluscw 187:92cbb9eec47b 127 _usage = usage;
apluscw 187:92cbb9eec47b 128 return 0;
apluscw 187:92cbb9eec47b 129 }
apluscw 187:92cbb9eec47b 130
apluscw 187:92cbb9eec47b 131 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)
apluscw 187:92cbb9eec47b 132 {
apluscw 187:92cbb9eec47b 133 #if TRANSACTION_QUEUE_SIZE_SPI
apluscw 187:92cbb9eec47b 134 transaction_t t;
apluscw 187:92cbb9eec47b 135
apluscw 187:92cbb9eec47b 136 t.tx_buffer = const_cast<void *>(tx_buffer);
apluscw 187:92cbb9eec47b 137 t.tx_length = tx_length;
apluscw 187:92cbb9eec47b 138 t.rx_buffer = rx_buffer;
apluscw 187:92cbb9eec47b 139 t.rx_length = rx_length;
apluscw 187:92cbb9eec47b 140 t.event = event;
apluscw 187:92cbb9eec47b 141 t.callback = callback;
apluscw 187:92cbb9eec47b 142 t.width = bit_width;
apluscw 187:92cbb9eec47b 143 Transaction<SPI> transaction(this, t);
apluscw 187:92cbb9eec47b 144 if (_transaction_buffer.full()) {
apluscw 187:92cbb9eec47b 145 return -1; // the buffer is full
apluscw 187:92cbb9eec47b 146 } else {
apluscw 187:92cbb9eec47b 147 core_util_critical_section_enter();
apluscw 187:92cbb9eec47b 148 _transaction_buffer.push(transaction);
apluscw 187:92cbb9eec47b 149 if (!spi_active(&_spi)) {
apluscw 187:92cbb9eec47b 150 dequeue_transaction();
apluscw 187:92cbb9eec47b 151 }
apluscw 187:92cbb9eec47b 152 core_util_critical_section_exit();
apluscw 187:92cbb9eec47b 153 return 0;
apluscw 187:92cbb9eec47b 154 }
apluscw 187:92cbb9eec47b 155 #else
apluscw 187:92cbb9eec47b 156 return -1;
apluscw 187:92cbb9eec47b 157 #endif
apluscw 187:92cbb9eec47b 158 }
apluscw 187:92cbb9eec47b 159
apluscw 187:92cbb9eec47b 160 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)
apluscw 187:92cbb9eec47b 161 {
apluscw 187:92cbb9eec47b 162 aquire();
apluscw 187:92cbb9eec47b 163 _callback = callback;
apluscw 187:92cbb9eec47b 164 _irq.callback(&SPI::irq_handler_asynch);
apluscw 187:92cbb9eec47b 165 spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event , _usage);
apluscw 187:92cbb9eec47b 166 }
apluscw 187:92cbb9eec47b 167
apluscw 187:92cbb9eec47b 168 #if TRANSACTION_QUEUE_SIZE_SPI
apluscw 187:92cbb9eec47b 169
apluscw 187:92cbb9eec47b 170 void SPI::start_transaction(transaction_t *data)
apluscw 187:92cbb9eec47b 171 {
apluscw 187:92cbb9eec47b 172 start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event);
apluscw 187:92cbb9eec47b 173 }
apluscw 187:92cbb9eec47b 174
apluscw 187:92cbb9eec47b 175 void SPI::dequeue_transaction()
apluscw 187:92cbb9eec47b 176 {
apluscw 187:92cbb9eec47b 177 Transaction<SPI> t;
apluscw 187:92cbb9eec47b 178 if (_transaction_buffer.pop(t)) {
apluscw 187:92cbb9eec47b 179 SPI* obj = t.get_object();
apluscw 187:92cbb9eec47b 180 transaction_t* data = t.get_transaction();
apluscw 187:92cbb9eec47b 181 obj->start_transaction(data);
apluscw 187:92cbb9eec47b 182 }
apluscw 187:92cbb9eec47b 183 }
apluscw 187:92cbb9eec47b 184
apluscw 187:92cbb9eec47b 185 #endif
apluscw 187:92cbb9eec47b 186
apluscw 187:92cbb9eec47b 187 void SPI::irq_handler_asynch(void)
apluscw 187:92cbb9eec47b 188 {
apluscw 187:92cbb9eec47b 189 int event = spi_irq_handler_asynch(&_spi);
apluscw 187:92cbb9eec47b 190 if (_callback && (event & SPI_EVENT_ALL)) {
apluscw 187:92cbb9eec47b 191 _callback.call(event & SPI_EVENT_ALL);
apluscw 187:92cbb9eec47b 192 }
apluscw 187:92cbb9eec47b 193 #if TRANSACTION_QUEUE_SIZE_SPI
apluscw 187:92cbb9eec47b 194 if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) {
apluscw 187:92cbb9eec47b 195 // SPI peripheral is free (event happend), dequeue transaction
apluscw 187:92cbb9eec47b 196 dequeue_transaction();
apluscw 187:92cbb9eec47b 197 }
apluscw 187:92cbb9eec47b 198 #endif
apluscw 187:92cbb9eec47b 199 }
apluscw 187:92cbb9eec47b 200
apluscw 187:92cbb9eec47b 201 #endif
apluscw 187:92cbb9eec47b 202
apluscw 187:92cbb9eec47b 203 } // namespace mbed
apluscw 187:92cbb9eec47b 204
apluscw 187:92cbb9eec47b 205 #endif