mbed-os for GR-LYCHEE

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

Committer:
dkato
Date:
Fri Feb 02 05:42:23 2018 +0000
Revision:
0:f782d9c66c49
mbed-os for GR-LYCHEE

Who changed what in which revision?

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