mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
updated based on mbed-os5.15.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 1:9db0e321a9f4 1 /* mbed Microcontroller Library
kenjiArai 1:9db0e321a9f4 2 * Copyright (c) 2006-2019 ARM Limited
kenjiArai 1:9db0e321a9f4 3 * SPDX-License-Identifier: Apache-2.0
kenjiArai 1:9db0e321a9f4 4 *
kenjiArai 1:9db0e321a9f4 5 * Licensed under the Apache License, Version 2.0 (the "License");
kenjiArai 1:9db0e321a9f4 6 * you may not use this file except in compliance with the License.
kenjiArai 1:9db0e321a9f4 7 * You may obtain a copy of the License at
kenjiArai 1:9db0e321a9f4 8 *
kenjiArai 1:9db0e321a9f4 9 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 1:9db0e321a9f4 10 *
kenjiArai 1:9db0e321a9f4 11 * Unless required by applicable law or agreed to in writing, software
kenjiArai 1:9db0e321a9f4 12 * distributed under the License is distributed on an "AS IS" BASIS,
kenjiArai 1:9db0e321a9f4 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 1:9db0e321a9f4 14 * See the License for the specific language governing permissions and
kenjiArai 1:9db0e321a9f4 15 * limitations under the License.
kenjiArai 1:9db0e321a9f4 16 */
kenjiArai 1:9db0e321a9f4 17 #include "drivers/SPI.h"
kenjiArai 1:9db0e321a9f4 18 #include "platform/mbed_critical.h"
kenjiArai 1:9db0e321a9f4 19
kenjiArai 1:9db0e321a9f4 20 #if DEVICE_SPI_ASYNCH
kenjiArai 1:9db0e321a9f4 21 #include "platform/mbed_power_mgmt.h"
kenjiArai 1:9db0e321a9f4 22 #endif
kenjiArai 1:9db0e321a9f4 23
kenjiArai 1:9db0e321a9f4 24 #if DEVICE_SPI
kenjiArai 1:9db0e321a9f4 25
kenjiArai 1:9db0e321a9f4 26 namespace mbed {
kenjiArai 1:9db0e321a9f4 27
kenjiArai 1:9db0e321a9f4 28 SPI::spi_peripheral_s SPI::_peripherals[SPI_PERIPHERALS_USED];
kenjiArai 1:9db0e321a9f4 29 int SPI::_peripherals_used;
kenjiArai 1:9db0e321a9f4 30
kenjiArai 1:9db0e321a9f4 31 SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) :
kenjiArai 1:9db0e321a9f4 32 #if DEVICE_SPI_ASYNCH
kenjiArai 1:9db0e321a9f4 33 _irq(this),
kenjiArai 1:9db0e321a9f4 34 #endif
kenjiArai 1:9db0e321a9f4 35 _mosi(mosi),
kenjiArai 1:9db0e321a9f4 36 _miso(miso),
kenjiArai 1:9db0e321a9f4 37 _sclk(sclk),
kenjiArai 1:9db0e321a9f4 38 _hw_ssel(ssel),
kenjiArai 1:9db0e321a9f4 39 _sw_ssel(NC),
kenjiArai 1:9db0e321a9f4 40 _static_pinmap(NULL),
kenjiArai 1:9db0e321a9f4 41 _init_func(_do_init)
kenjiArai 1:9db0e321a9f4 42 {
kenjiArai 1:9db0e321a9f4 43 // Need backwards compatibility with HALs not providing API
kenjiArai 1:9db0e321a9f4 44 #ifdef DEVICE_SPI_COUNT
kenjiArai 1:9db0e321a9f4 45 _peripheral_name = spi_get_peripheral_name(_mosi, _miso, _sclk);
kenjiArai 1:9db0e321a9f4 46 #else
kenjiArai 1:9db0e321a9f4 47 _peripheral_name = GlobalSPI;
kenjiArai 1:9db0e321a9f4 48 #endif
kenjiArai 1:9db0e321a9f4 49
kenjiArai 1:9db0e321a9f4 50 _do_construct();
kenjiArai 1:9db0e321a9f4 51 }
kenjiArai 1:9db0e321a9f4 52
kenjiArai 1:9db0e321a9f4 53 SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel, use_gpio_ssel_t) :
kenjiArai 1:9db0e321a9f4 54 #if DEVICE_SPI_ASYNCH
kenjiArai 1:9db0e321a9f4 55 _irq(this),
kenjiArai 1:9db0e321a9f4 56 #endif
kenjiArai 1:9db0e321a9f4 57 _mosi(mosi),
kenjiArai 1:9db0e321a9f4 58 _miso(miso),
kenjiArai 1:9db0e321a9f4 59 _sclk(sclk),
kenjiArai 1:9db0e321a9f4 60 _hw_ssel(NC),
kenjiArai 1:9db0e321a9f4 61 _sw_ssel(ssel, 1),
kenjiArai 1:9db0e321a9f4 62 _static_pinmap(NULL),
kenjiArai 1:9db0e321a9f4 63 _init_func(_do_init)
kenjiArai 1:9db0e321a9f4 64 {
kenjiArai 1:9db0e321a9f4 65 // Need backwards compatibility with HALs not providing API
kenjiArai 1:9db0e321a9f4 66 #ifdef DEVICE_SPI_COUNT
kenjiArai 1:9db0e321a9f4 67 _peripheral_name = spi_get_peripheral_name(_mosi, _miso, _sclk);
kenjiArai 1:9db0e321a9f4 68 #else
kenjiArai 1:9db0e321a9f4 69 _peripheral_name = GlobalSPI;
kenjiArai 1:9db0e321a9f4 70 #endif
kenjiArai 1:9db0e321a9f4 71 _do_construct();
kenjiArai 1:9db0e321a9f4 72 }
kenjiArai 1:9db0e321a9f4 73
kenjiArai 1:9db0e321a9f4 74 SPI::SPI(const spi_pinmap_t &pinmap) :
kenjiArai 1:9db0e321a9f4 75 #if DEVICE_SPI_ASYNCH
kenjiArai 1:9db0e321a9f4 76 _irq(this),
kenjiArai 1:9db0e321a9f4 77 #endif
kenjiArai 1:9db0e321a9f4 78 _mosi(pinmap.mosi_pin),
kenjiArai 1:9db0e321a9f4 79 _miso(pinmap.miso_pin),
kenjiArai 1:9db0e321a9f4 80 _sclk(pinmap.sclk_pin),
kenjiArai 1:9db0e321a9f4 81 _hw_ssel(pinmap.ssel_pin),
kenjiArai 1:9db0e321a9f4 82 _sw_ssel(NC),
kenjiArai 1:9db0e321a9f4 83 _static_pinmap(&pinmap),
kenjiArai 1:9db0e321a9f4 84 _peripheral_name((SPIName)pinmap.peripheral),
kenjiArai 1:9db0e321a9f4 85 _init_func(_do_init_direct)
kenjiArai 1:9db0e321a9f4 86
kenjiArai 1:9db0e321a9f4 87 {
kenjiArai 1:9db0e321a9f4 88 _do_construct();
kenjiArai 1:9db0e321a9f4 89 }
kenjiArai 1:9db0e321a9f4 90
kenjiArai 1:9db0e321a9f4 91 SPI::SPI(const spi_pinmap_t &pinmap, PinName ssel) :
kenjiArai 1:9db0e321a9f4 92 #if DEVICE_SPI_ASYNCH
kenjiArai 1:9db0e321a9f4 93 _irq(this),
kenjiArai 1:9db0e321a9f4 94 #endif
kenjiArai 1:9db0e321a9f4 95 _mosi(pinmap.mosi_pin),
kenjiArai 1:9db0e321a9f4 96 _miso(pinmap.miso_pin),
kenjiArai 1:9db0e321a9f4 97 _sclk(pinmap.sclk_pin),
kenjiArai 1:9db0e321a9f4 98 _hw_ssel(NC),
kenjiArai 1:9db0e321a9f4 99 _sw_ssel(ssel, 1),
kenjiArai 1:9db0e321a9f4 100 _static_pinmap(&pinmap),
kenjiArai 1:9db0e321a9f4 101 _peripheral_name((SPIName)pinmap.peripheral),
kenjiArai 1:9db0e321a9f4 102 _init_func(_do_init_direct)
kenjiArai 1:9db0e321a9f4 103 {
kenjiArai 1:9db0e321a9f4 104 _do_construct();
kenjiArai 1:9db0e321a9f4 105 }
kenjiArai 1:9db0e321a9f4 106
kenjiArai 1:9db0e321a9f4 107 void SPI::_do_init(SPI *obj)
kenjiArai 1:9db0e321a9f4 108 {
kenjiArai 1:9db0e321a9f4 109 spi_init(&obj->_peripheral->spi, obj->_mosi, obj->_miso, obj->_sclk, obj->_hw_ssel);
kenjiArai 1:9db0e321a9f4 110 }
kenjiArai 1:9db0e321a9f4 111
kenjiArai 1:9db0e321a9f4 112 void SPI::_do_init_direct(SPI *obj)
kenjiArai 1:9db0e321a9f4 113 {
kenjiArai 1:9db0e321a9f4 114 spi_init_direct(&obj->_peripheral->spi, obj->_static_pinmap);
kenjiArai 1:9db0e321a9f4 115 }
kenjiArai 1:9db0e321a9f4 116
kenjiArai 1:9db0e321a9f4 117 void SPI::_do_construct()
kenjiArai 1:9db0e321a9f4 118 {
kenjiArai 1:9db0e321a9f4 119 // No lock needed in the constructor
kenjiArai 1:9db0e321a9f4 120 #if DEVICE_SPI_ASYNCH
kenjiArai 1:9db0e321a9f4 121 _usage = DMA_USAGE_NEVER;
kenjiArai 1:9db0e321a9f4 122 _deep_sleep_locked = false;
kenjiArai 1:9db0e321a9f4 123 #endif
kenjiArai 1:9db0e321a9f4 124 _select_count = 0;
kenjiArai 1:9db0e321a9f4 125 _bits = 8;
kenjiArai 1:9db0e321a9f4 126 _mode = 0;
kenjiArai 1:9db0e321a9f4 127 _hz = 1000000;
kenjiArai 1:9db0e321a9f4 128 _write_fill = SPI_FILL_CHAR;
kenjiArai 1:9db0e321a9f4 129
kenjiArai 1:9db0e321a9f4 130 core_util_critical_section_enter();
kenjiArai 1:9db0e321a9f4 131 // lookup in a critical section if we already have it else initialize it
kenjiArai 1:9db0e321a9f4 132
kenjiArai 1:9db0e321a9f4 133 _peripheral = SPI::_lookup(_peripheral_name);
kenjiArai 1:9db0e321a9f4 134 if (!_peripheral) {
kenjiArai 1:9db0e321a9f4 135 _peripheral = SPI::_alloc();
kenjiArai 1:9db0e321a9f4 136 _peripheral->name = _peripheral_name;
kenjiArai 1:9db0e321a9f4 137 }
kenjiArai 1:9db0e321a9f4 138 core_util_critical_section_exit();
kenjiArai 1:9db0e321a9f4 139
kenjiArai 1:9db0e321a9f4 140 #if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI
kenjiArai 1:9db0e321a9f4 141 // prime the SingletonPtr, so we don't have a problem trying to
kenjiArai 1:9db0e321a9f4 142 // construct the buffer if asynch operation initiated from IRQ
kenjiArai 1:9db0e321a9f4 143 _peripheral->transaction_buffer.get();
kenjiArai 1:9db0e321a9f4 144 #endif
kenjiArai 1:9db0e321a9f4 145 // we don't need to _acquire at this stage.
kenjiArai 1:9db0e321a9f4 146 // this will be done anyway before any operation.
kenjiArai 1:9db0e321a9f4 147 }
kenjiArai 1:9db0e321a9f4 148
kenjiArai 1:9db0e321a9f4 149 SPI::~SPI()
kenjiArai 1:9db0e321a9f4 150 {
kenjiArai 1:9db0e321a9f4 151 lock();
kenjiArai 1:9db0e321a9f4 152 /* Make sure a stale pointer isn't left in peripheral's owner field */
kenjiArai 1:9db0e321a9f4 153 if (_peripheral->owner == this) {
kenjiArai 1:9db0e321a9f4 154 _peripheral->owner = NULL;
kenjiArai 1:9db0e321a9f4 155 }
kenjiArai 1:9db0e321a9f4 156 unlock();
kenjiArai 1:9db0e321a9f4 157 }
kenjiArai 1:9db0e321a9f4 158
kenjiArai 1:9db0e321a9f4 159 SPI::spi_peripheral_s *SPI::_lookup(SPI::SPIName name)
kenjiArai 1:9db0e321a9f4 160 {
kenjiArai 1:9db0e321a9f4 161 SPI::spi_peripheral_s *result = NULL;
kenjiArai 1:9db0e321a9f4 162 core_util_critical_section_enter();
kenjiArai 1:9db0e321a9f4 163 for (int idx = 0; idx < _peripherals_used; idx++) {
kenjiArai 1:9db0e321a9f4 164 if (_peripherals[idx].name == name) {
kenjiArai 1:9db0e321a9f4 165 result = &_peripherals[idx];
kenjiArai 1:9db0e321a9f4 166 break;
kenjiArai 1:9db0e321a9f4 167 }
kenjiArai 1:9db0e321a9f4 168 }
kenjiArai 1:9db0e321a9f4 169 core_util_critical_section_exit();
kenjiArai 1:9db0e321a9f4 170 return result;
kenjiArai 1:9db0e321a9f4 171 }
kenjiArai 1:9db0e321a9f4 172
kenjiArai 1:9db0e321a9f4 173 SPI::spi_peripheral_s *SPI::_alloc()
kenjiArai 1:9db0e321a9f4 174 {
kenjiArai 1:9db0e321a9f4 175 MBED_ASSERT(_peripherals_used < SPI_PERIPHERALS_USED);
kenjiArai 1:9db0e321a9f4 176 return &_peripherals[_peripherals_used++];
kenjiArai 1:9db0e321a9f4 177 }
kenjiArai 1:9db0e321a9f4 178
kenjiArai 1:9db0e321a9f4 179 void SPI::format(int bits, int mode)
kenjiArai 1:9db0e321a9f4 180 {
kenjiArai 1:9db0e321a9f4 181 lock();
kenjiArai 1:9db0e321a9f4 182 _bits = bits;
kenjiArai 1:9db0e321a9f4 183 _mode = mode;
kenjiArai 1:9db0e321a9f4 184 // If changing format while you are the owner then just
kenjiArai 1:9db0e321a9f4 185 // update format, but if owner is changed then even frequency should be
kenjiArai 1:9db0e321a9f4 186 // updated which is done by acquire.
kenjiArai 1:9db0e321a9f4 187 if (_peripheral->owner == this) {
kenjiArai 1:9db0e321a9f4 188 spi_format(&_peripheral->spi, _bits, _mode, 0);
kenjiArai 1:9db0e321a9f4 189 } else {
kenjiArai 1:9db0e321a9f4 190 _acquire();
kenjiArai 1:9db0e321a9f4 191 }
kenjiArai 1:9db0e321a9f4 192 unlock();
kenjiArai 1:9db0e321a9f4 193 }
kenjiArai 1:9db0e321a9f4 194
kenjiArai 1:9db0e321a9f4 195 void SPI::frequency(int hz)
kenjiArai 1:9db0e321a9f4 196 {
kenjiArai 1:9db0e321a9f4 197 lock();
kenjiArai 1:9db0e321a9f4 198 _hz = hz;
kenjiArai 1:9db0e321a9f4 199 // If changing format while you are the owner then just
kenjiArai 1:9db0e321a9f4 200 // update frequency, but if owner is changed then even frequency should be
kenjiArai 1:9db0e321a9f4 201 // updated which is done by acquire.
kenjiArai 1:9db0e321a9f4 202 if (_peripheral->owner == this) {
kenjiArai 1:9db0e321a9f4 203 spi_frequency(&_peripheral->spi, _hz);
kenjiArai 1:9db0e321a9f4 204 } else {
kenjiArai 1:9db0e321a9f4 205 _acquire();
kenjiArai 1:9db0e321a9f4 206 }
kenjiArai 1:9db0e321a9f4 207 unlock();
kenjiArai 1:9db0e321a9f4 208 }
kenjiArai 1:9db0e321a9f4 209
kenjiArai 1:9db0e321a9f4 210 // Note: Private function with no locking
kenjiArai 1:9db0e321a9f4 211 void SPI::_acquire()
kenjiArai 1:9db0e321a9f4 212 {
kenjiArai 1:9db0e321a9f4 213 if (_peripheral->owner != this) {
kenjiArai 1:9db0e321a9f4 214 _init_func(this);
kenjiArai 1:9db0e321a9f4 215 spi_format(&_peripheral->spi, _bits, _mode, 0);
kenjiArai 1:9db0e321a9f4 216 spi_frequency(&_peripheral->spi, _hz);
kenjiArai 1:9db0e321a9f4 217 _peripheral->owner = this;
kenjiArai 1:9db0e321a9f4 218 }
kenjiArai 1:9db0e321a9f4 219 }
kenjiArai 1:9db0e321a9f4 220
kenjiArai 1:9db0e321a9f4 221 int SPI::write(int value)
kenjiArai 1:9db0e321a9f4 222 {
kenjiArai 1:9db0e321a9f4 223 select();
kenjiArai 1:9db0e321a9f4 224 int ret = spi_master_write(&_peripheral->spi, value);
kenjiArai 1:9db0e321a9f4 225 deselect();
kenjiArai 1:9db0e321a9f4 226 return ret;
kenjiArai 1:9db0e321a9f4 227 }
kenjiArai 1:9db0e321a9f4 228
kenjiArai 1:9db0e321a9f4 229 int SPI::write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length)
kenjiArai 1:9db0e321a9f4 230 {
kenjiArai 1:9db0e321a9f4 231 select();
kenjiArai 1:9db0e321a9f4 232 int ret = spi_master_block_write(&_peripheral->spi, tx_buffer, tx_length, rx_buffer, rx_length, _write_fill);
kenjiArai 1:9db0e321a9f4 233 deselect();
kenjiArai 1:9db0e321a9f4 234 return ret;
kenjiArai 1:9db0e321a9f4 235 }
kenjiArai 1:9db0e321a9f4 236
kenjiArai 1:9db0e321a9f4 237 void SPI::_set_ssel(int val)
kenjiArai 1:9db0e321a9f4 238 {
kenjiArai 1:9db0e321a9f4 239 if (_sw_ssel.is_connected()) {
kenjiArai 1:9db0e321a9f4 240 _sw_ssel = val;
kenjiArai 1:9db0e321a9f4 241 }
kenjiArai 1:9db0e321a9f4 242 }
kenjiArai 1:9db0e321a9f4 243
kenjiArai 1:9db0e321a9f4 244 void SPI::lock()
kenjiArai 1:9db0e321a9f4 245 {
kenjiArai 1:9db0e321a9f4 246 _peripheral->mutex->lock();
kenjiArai 1:9db0e321a9f4 247 }
kenjiArai 1:9db0e321a9f4 248
kenjiArai 1:9db0e321a9f4 249 void SPI::select()
kenjiArai 1:9db0e321a9f4 250 {
kenjiArai 1:9db0e321a9f4 251 lock();
kenjiArai 1:9db0e321a9f4 252 if (_select_count++ == 0) {
kenjiArai 1:9db0e321a9f4 253 _acquire();
kenjiArai 1:9db0e321a9f4 254 _set_ssel(0);
kenjiArai 1:9db0e321a9f4 255 }
kenjiArai 1:9db0e321a9f4 256 }
kenjiArai 1:9db0e321a9f4 257
kenjiArai 1:9db0e321a9f4 258 void SPI::unlock()
kenjiArai 1:9db0e321a9f4 259 {
kenjiArai 1:9db0e321a9f4 260 _peripheral->mutex->unlock();
kenjiArai 1:9db0e321a9f4 261 }
kenjiArai 1:9db0e321a9f4 262
kenjiArai 1:9db0e321a9f4 263 void SPI::deselect()
kenjiArai 1:9db0e321a9f4 264 {
kenjiArai 1:9db0e321a9f4 265 if (--_select_count == 0) {
kenjiArai 1:9db0e321a9f4 266 _set_ssel(1);
kenjiArai 1:9db0e321a9f4 267 }
kenjiArai 1:9db0e321a9f4 268 unlock();
kenjiArai 1:9db0e321a9f4 269 }
kenjiArai 1:9db0e321a9f4 270
kenjiArai 1:9db0e321a9f4 271 void SPI::set_default_write_value(char data)
kenjiArai 1:9db0e321a9f4 272 {
kenjiArai 1:9db0e321a9f4 273 // this does not actually need to lock the peripheral.
kenjiArai 1:9db0e321a9f4 274 lock();
kenjiArai 1:9db0e321a9f4 275 _write_fill = data;
kenjiArai 1:9db0e321a9f4 276 unlock();
kenjiArai 1:9db0e321a9f4 277 }
kenjiArai 1:9db0e321a9f4 278
kenjiArai 1:9db0e321a9f4 279 #if DEVICE_SPI_ASYNCH
kenjiArai 1:9db0e321a9f4 280
kenjiArai 1:9db0e321a9f4 281 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)
kenjiArai 1:9db0e321a9f4 282 {
kenjiArai 1:9db0e321a9f4 283 if (spi_active(&_peripheral->spi)) {
kenjiArai 1:9db0e321a9f4 284 return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
kenjiArai 1:9db0e321a9f4 285 }
kenjiArai 1:9db0e321a9f4 286 start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event);
kenjiArai 1:9db0e321a9f4 287 return 0;
kenjiArai 1:9db0e321a9f4 288 }
kenjiArai 1:9db0e321a9f4 289
kenjiArai 1:9db0e321a9f4 290 void SPI::abort_transfer()
kenjiArai 1:9db0e321a9f4 291 {
kenjiArai 1:9db0e321a9f4 292 spi_abort_asynch(&_peripheral->spi);
kenjiArai 1:9db0e321a9f4 293 unlock_deep_sleep();
kenjiArai 1:9db0e321a9f4 294 #if TRANSACTION_QUEUE_SIZE_SPI
kenjiArai 1:9db0e321a9f4 295 dequeue_transaction();
kenjiArai 1:9db0e321a9f4 296 #endif
kenjiArai 1:9db0e321a9f4 297 }
kenjiArai 1:9db0e321a9f4 298
kenjiArai 1:9db0e321a9f4 299 void SPI::clear_transfer_buffer()
kenjiArai 1:9db0e321a9f4 300 {
kenjiArai 1:9db0e321a9f4 301 #if TRANSACTION_QUEUE_SIZE_SPI
kenjiArai 1:9db0e321a9f4 302 _peripheral->transaction_buffer->reset();
kenjiArai 1:9db0e321a9f4 303 #endif
kenjiArai 1:9db0e321a9f4 304 }
kenjiArai 1:9db0e321a9f4 305
kenjiArai 1:9db0e321a9f4 306 void SPI::abort_all_transfers()
kenjiArai 1:9db0e321a9f4 307 {
kenjiArai 1:9db0e321a9f4 308 clear_transfer_buffer();
kenjiArai 1:9db0e321a9f4 309 abort_transfer();
kenjiArai 1:9db0e321a9f4 310 }
kenjiArai 1:9db0e321a9f4 311
kenjiArai 1:9db0e321a9f4 312 int SPI::set_dma_usage(DMAUsage usage)
kenjiArai 1:9db0e321a9f4 313 {
kenjiArai 1:9db0e321a9f4 314 if (spi_active(&_peripheral->spi)) {
kenjiArai 1:9db0e321a9f4 315 return -1;
kenjiArai 1:9db0e321a9f4 316 }
kenjiArai 1:9db0e321a9f4 317 _usage = usage;
kenjiArai 1:9db0e321a9f4 318 return 0;
kenjiArai 1:9db0e321a9f4 319 }
kenjiArai 1:9db0e321a9f4 320
kenjiArai 1:9db0e321a9f4 321 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)
kenjiArai 1:9db0e321a9f4 322 {
kenjiArai 1:9db0e321a9f4 323 #if TRANSACTION_QUEUE_SIZE_SPI
kenjiArai 1:9db0e321a9f4 324 transaction_t t;
kenjiArai 1:9db0e321a9f4 325
kenjiArai 1:9db0e321a9f4 326 t.tx_buffer = const_cast<void *>(tx_buffer);
kenjiArai 1:9db0e321a9f4 327 t.tx_length = tx_length;
kenjiArai 1:9db0e321a9f4 328 t.rx_buffer = rx_buffer;
kenjiArai 1:9db0e321a9f4 329 t.rx_length = rx_length;
kenjiArai 1:9db0e321a9f4 330 t.event = event;
kenjiArai 1:9db0e321a9f4 331 t.callback = callback;
kenjiArai 1:9db0e321a9f4 332 t.width = bit_width;
kenjiArai 1:9db0e321a9f4 333 Transaction<SPI> transaction(this, t);
kenjiArai 1:9db0e321a9f4 334 if (_peripheral->transaction_buffer->full()) {
kenjiArai 1:9db0e321a9f4 335 return -1; // the buffer is full
kenjiArai 1:9db0e321a9f4 336 } else {
kenjiArai 1:9db0e321a9f4 337 core_util_critical_section_enter();
kenjiArai 1:9db0e321a9f4 338 _peripheral->transaction_buffer->push(transaction);
kenjiArai 1:9db0e321a9f4 339 if (!spi_active(&_peripheral->spi)) {
kenjiArai 1:9db0e321a9f4 340 dequeue_transaction();
kenjiArai 1:9db0e321a9f4 341 }
kenjiArai 1:9db0e321a9f4 342 core_util_critical_section_exit();
kenjiArai 1:9db0e321a9f4 343 return 0;
kenjiArai 1:9db0e321a9f4 344 }
kenjiArai 1:9db0e321a9f4 345 #else
kenjiArai 1:9db0e321a9f4 346 return -1;
kenjiArai 1:9db0e321a9f4 347 #endif
kenjiArai 1:9db0e321a9f4 348 }
kenjiArai 1:9db0e321a9f4 349
kenjiArai 1:9db0e321a9f4 350 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)
kenjiArai 1:9db0e321a9f4 351 {
kenjiArai 1:9db0e321a9f4 352 lock_deep_sleep();
kenjiArai 1:9db0e321a9f4 353 _acquire();
kenjiArai 1:9db0e321a9f4 354 _set_ssel(0);
kenjiArai 1:9db0e321a9f4 355 _callback = callback;
kenjiArai 1:9db0e321a9f4 356 _irq.callback(&SPI::irq_handler_asynch);
kenjiArai 1:9db0e321a9f4 357 spi_master_transfer(&_peripheral->spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event, _usage);
kenjiArai 1:9db0e321a9f4 358 }
kenjiArai 1:9db0e321a9f4 359
kenjiArai 1:9db0e321a9f4 360 void SPI::lock_deep_sleep()
kenjiArai 1:9db0e321a9f4 361 {
kenjiArai 1:9db0e321a9f4 362 if (_deep_sleep_locked == false) {
kenjiArai 1:9db0e321a9f4 363 sleep_manager_lock_deep_sleep();
kenjiArai 1:9db0e321a9f4 364 _deep_sleep_locked = true;
kenjiArai 1:9db0e321a9f4 365 }
kenjiArai 1:9db0e321a9f4 366 }
kenjiArai 1:9db0e321a9f4 367
kenjiArai 1:9db0e321a9f4 368 void SPI::unlock_deep_sleep()
kenjiArai 1:9db0e321a9f4 369 {
kenjiArai 1:9db0e321a9f4 370 if (_deep_sleep_locked == true) {
kenjiArai 1:9db0e321a9f4 371 sleep_manager_unlock_deep_sleep();
kenjiArai 1:9db0e321a9f4 372 _deep_sleep_locked = false;
kenjiArai 1:9db0e321a9f4 373 }
kenjiArai 1:9db0e321a9f4 374 }
kenjiArai 1:9db0e321a9f4 375
kenjiArai 1:9db0e321a9f4 376 #if TRANSACTION_QUEUE_SIZE_SPI
kenjiArai 1:9db0e321a9f4 377
kenjiArai 1:9db0e321a9f4 378 void SPI::start_transaction(transaction_t *data)
kenjiArai 1:9db0e321a9f4 379 {
kenjiArai 1:9db0e321a9f4 380 start_transfer(data->tx_buffer, data->tx_length, data->rx_buffer, data->rx_length, data->width, data->callback, data->event);
kenjiArai 1:9db0e321a9f4 381 }
kenjiArai 1:9db0e321a9f4 382
kenjiArai 1:9db0e321a9f4 383 void SPI::dequeue_transaction()
kenjiArai 1:9db0e321a9f4 384 {
kenjiArai 1:9db0e321a9f4 385 Transaction<SPI> t;
kenjiArai 1:9db0e321a9f4 386 if (_peripheral->transaction_buffer->pop(t)) {
kenjiArai 1:9db0e321a9f4 387 SPI *obj = t.get_object();
kenjiArai 1:9db0e321a9f4 388 transaction_t *data = t.get_transaction();
kenjiArai 1:9db0e321a9f4 389 obj->start_transaction(data);
kenjiArai 1:9db0e321a9f4 390 }
kenjiArai 1:9db0e321a9f4 391 }
kenjiArai 1:9db0e321a9f4 392
kenjiArai 1:9db0e321a9f4 393 #endif
kenjiArai 1:9db0e321a9f4 394
kenjiArai 1:9db0e321a9f4 395 void SPI::irq_handler_asynch(void)
kenjiArai 1:9db0e321a9f4 396 {
kenjiArai 1:9db0e321a9f4 397 int event = spi_irq_handler_asynch(&_peripheral->spi);
kenjiArai 1:9db0e321a9f4 398 if (_callback && (event & SPI_EVENT_ALL)) {
kenjiArai 1:9db0e321a9f4 399 _set_ssel(1);
kenjiArai 1:9db0e321a9f4 400 unlock_deep_sleep();
kenjiArai 1:9db0e321a9f4 401 _callback.call(event & SPI_EVENT_ALL);
kenjiArai 1:9db0e321a9f4 402 }
kenjiArai 1:9db0e321a9f4 403 #if TRANSACTION_QUEUE_SIZE_SPI
kenjiArai 1:9db0e321a9f4 404 if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) {
kenjiArai 1:9db0e321a9f4 405 // SPI peripheral is free (event happened), dequeue transaction
kenjiArai 1:9db0e321a9f4 406 dequeue_transaction();
kenjiArai 1:9db0e321a9f4 407 }
kenjiArai 1:9db0e321a9f4 408 #endif
kenjiArai 1:9db0e321a9f4 409 }
kenjiArai 1:9db0e321a9f4 410
kenjiArai 1:9db0e321a9f4 411 #endif
kenjiArai 1:9db0e321a9f4 412
kenjiArai 1:9db0e321a9f4 413 } // namespace mbed
kenjiArai 1:9db0e321a9f4 414
kenjiArai 1:9db0e321a9f4 415 #endif