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