USB Serial application

Fork of USBSerial_HelloWorld by Samuel Mokrani

Committer:
Zaitsev
Date:
Tue Jan 10 20:42:26 2017 +0000
Revision:
10:41552d038a69
USB Serial bi-directional bridge

Who changed what in which revision?

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