Rtos API example

Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

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