Morpheus / mbed-hal

Dependencies:   target-freescale

Committer:
screamer
Date:
Wed Mar 23 21:36:09 2016 +0000
Revision:
0:9c59db1fbc9e
Initial revision

Who changed what in which revision?

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