max32630fthr quad spi , unexpected spi behavior

Committer:
boonshen
Date:
Tue Mar 13 21:12:00 2018 +0000
Revision:
0:a35c40f49345
MAX32630FTHR QuadSPI test

Who changed what in which revision?

UserRevisionLine numberNew contents of line
boonshen 0:a35c40f49345 1 /* mbed Microcontroller Library
boonshen 0:a35c40f49345 2 * Copyright (c) 2006-2015 ARM Limited
boonshen 0:a35c40f49345 3 *
boonshen 0:a35c40f49345 4 * Licensed under the Apache License, Version 2.0 (the "License");
boonshen 0:a35c40f49345 5 * you may not use this file except in compliance with the License.
boonshen 0:a35c40f49345 6 * You may obtain a copy of the License at
boonshen 0:a35c40f49345 7 *
boonshen 0:a35c40f49345 8 * http://www.apache.org/licenses/LICENSE-2.0
boonshen 0:a35c40f49345 9 *
boonshen 0:a35c40f49345 10 * Unless required by applicable law or agreed to in writing, software
boonshen 0:a35c40f49345 11 * distributed under the License is distributed on an "AS IS" BASIS,
boonshen 0:a35c40f49345 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
boonshen 0:a35c40f49345 13 * See the License for the specific language governing permissions and
boonshen 0:a35c40f49345 14 * limitations under the License.
boonshen 0:a35c40f49345 15 */
boonshen 0:a35c40f49345 16 #ifndef MBED_SPI_H
boonshen 0:a35c40f49345 17 #define MBED_SPI_H
boonshen 0:a35c40f49345 18
boonshen 0:a35c40f49345 19 #include "platform/platform.h"
boonshen 0:a35c40f49345 20
boonshen 0:a35c40f49345 21 #if defined (DEVICE_SPI) || defined(DOXYGEN_ONLY)
boonshen 0:a35c40f49345 22
boonshen 0:a35c40f49345 23 #include "platform/PlatformMutex.h"
boonshen 0:a35c40f49345 24 #include "hal/spi_api.h"
boonshen 0:a35c40f49345 25 #include "platform/SingletonPtr.h"
boonshen 0:a35c40f49345 26 #include "platform/NonCopyable.h"
boonshen 0:a35c40f49345 27
boonshen 0:a35c40f49345 28 #if DEVICE_SPI_ASYNCH
boonshen 0:a35c40f49345 29 #include "platform/CThunk.h"
boonshen 0:a35c40f49345 30 #include "hal/dma_api.h"
boonshen 0:a35c40f49345 31 #include "platform/CircularBuffer.h"
boonshen 0:a35c40f49345 32 #include "platform/FunctionPointer.h"
boonshen 0:a35c40f49345 33 #include "platform/Transaction.h"
boonshen 0:a35c40f49345 34 #endif
boonshen 0:a35c40f49345 35
boonshen 0:a35c40f49345 36 namespace mbed {
boonshen 0:a35c40f49345 37 /** \addtogroup drivers */
boonshen 0:a35c40f49345 38
boonshen 0:a35c40f49345 39 /** A SPI Master, used for communicating with SPI slave devices
boonshen 0:a35c40f49345 40 *
boonshen 0:a35c40f49345 41 * The default format is set to 8-bits, mode 0, and a clock frequency of 1MHz
boonshen 0:a35c40f49345 42 *
boonshen 0:a35c40f49345 43 * Most SPI devices will also require Chip Select and Reset signals. These
boonshen 0:a35c40f49345 44 * can be controlled using DigitalOut pins
boonshen 0:a35c40f49345 45 *
boonshen 0:a35c40f49345 46 * @note Synchronization level: Thread safe
boonshen 0:a35c40f49345 47 *
boonshen 0:a35c40f49345 48 * Example:
boonshen 0:a35c40f49345 49 * @code
boonshen 0:a35c40f49345 50 * // Send a byte to a SPI slave, and record the response
boonshen 0:a35c40f49345 51 *
boonshen 0:a35c40f49345 52 * #include "mbed.h"
boonshen 0:a35c40f49345 53 *
boonshen 0:a35c40f49345 54 * // hardware ssel (where applicable)
boonshen 0:a35c40f49345 55 * //SPI device(p5, p6, p7, p8); // mosi, miso, sclk, ssel
boonshen 0:a35c40f49345 56 *
boonshen 0:a35c40f49345 57 * // software ssel
boonshen 0:a35c40f49345 58 * SPI device(p5, p6, p7); // mosi, miso, sclk
boonshen 0:a35c40f49345 59 * DigitalOut cs(p8); // ssel
boonshen 0:a35c40f49345 60 *
boonshen 0:a35c40f49345 61 * int main() {
boonshen 0:a35c40f49345 62 * // hardware ssel (where applicable)
boonshen 0:a35c40f49345 63 * //int response = device.write(0xFF);
boonshen 0:a35c40f49345 64 *
boonshen 0:a35c40f49345 65 * device.lock();
boonshen 0:a35c40f49345 66 * // software ssel
boonshen 0:a35c40f49345 67 * cs = 0;
boonshen 0:a35c40f49345 68 * int response = device.write(0xFF);
boonshen 0:a35c40f49345 69 * cs = 1;
boonshen 0:a35c40f49345 70 * device.unlock();
boonshen 0:a35c40f49345 71 *
boonshen 0:a35c40f49345 72 * }
boonshen 0:a35c40f49345 73 * @endcode
boonshen 0:a35c40f49345 74 * @ingroup drivers
boonshen 0:a35c40f49345 75 */
boonshen 0:a35c40f49345 76 class SPI : private NonCopyable<SPI> {
boonshen 0:a35c40f49345 77
boonshen 0:a35c40f49345 78 public:
boonshen 0:a35c40f49345 79
boonshen 0:a35c40f49345 80 /** Create a SPI master connected to the specified pins
boonshen 0:a35c40f49345 81 *
boonshen 0:a35c40f49345 82 * mosi or miso can be specfied as NC if not used
boonshen 0:a35c40f49345 83 *
boonshen 0:a35c40f49345 84 * @param mosi SPI Master Out, Slave In pin
boonshen 0:a35c40f49345 85 * @param miso SPI Master In, Slave Out pin
boonshen 0:a35c40f49345 86 * @param sclk SPI Clock pin
boonshen 0:a35c40f49345 87 * @param ssel SPI chip select pin
boonshen 0:a35c40f49345 88 */
boonshen 0:a35c40f49345 89 SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel=NC);
boonshen 0:a35c40f49345 90
boonshen 0:a35c40f49345 91 /** Configure the data transmission format
boonshen 0:a35c40f49345 92 *
boonshen 0:a35c40f49345 93 * @param bits Number of bits per SPI frame (4 - 16)
boonshen 0:a35c40f49345 94 * @param mode Clock polarity and phase mode (0 - 3)
boonshen 0:a35c40f49345 95 *
boonshen 0:a35c40f49345 96 * @code
boonshen 0:a35c40f49345 97 * mode | POL PHA
boonshen 0:a35c40f49345 98 * -----+--------
boonshen 0:a35c40f49345 99 * 0 | 0 0
boonshen 0:a35c40f49345 100 * 1 | 0 1
boonshen 0:a35c40f49345 101 * 2 | 1 0
boonshen 0:a35c40f49345 102 * 3 | 1 1
boonshen 0:a35c40f49345 103 * @endcode
boonshen 0:a35c40f49345 104 */
boonshen 0:a35c40f49345 105 void format(int bits, int mode = 0);
boonshen 0:a35c40f49345 106
boonshen 0:a35c40f49345 107 /** Set the spi bus clock frequency
boonshen 0:a35c40f49345 108 *
boonshen 0:a35c40f49345 109 * @param hz SCLK frequency in hz (default = 1MHz)
boonshen 0:a35c40f49345 110 */
boonshen 0:a35c40f49345 111 void frequency(int hz = 1000000);
boonshen 0:a35c40f49345 112
boonshen 0:a35c40f49345 113 /** Write to the SPI Slave and return the response
boonshen 0:a35c40f49345 114 *
boonshen 0:a35c40f49345 115 * @param value Data to be sent to the SPI slave
boonshen 0:a35c40f49345 116 *
boonshen 0:a35c40f49345 117 * @returns
boonshen 0:a35c40f49345 118 * Response from the SPI slave
boonshen 0:a35c40f49345 119 */
boonshen 0:a35c40f49345 120 virtual int write(int value);
boonshen 0:a35c40f49345 121
boonshen 0:a35c40f49345 122 /** Write to the SPI Slave and obtain the response
boonshen 0:a35c40f49345 123 *
boonshen 0:a35c40f49345 124 * The total number of bytes sent and recieved will be the maximum of
boonshen 0:a35c40f49345 125 * tx_length and rx_length. The bytes written will be padded with the
boonshen 0:a35c40f49345 126 * value 0xff.
boonshen 0:a35c40f49345 127 *
boonshen 0:a35c40f49345 128 * @param tx_buffer Pointer to the byte-array of data to write to the device
boonshen 0:a35c40f49345 129 * @param tx_length Number of bytes to write, may be zero
boonshen 0:a35c40f49345 130 * @param rx_buffer Pointer to the byte-array of data to read from the device
boonshen 0:a35c40f49345 131 * @param rx_length Number of bytes to read, may be zero
boonshen 0:a35c40f49345 132 * @returns
boonshen 0:a35c40f49345 133 * The number of bytes written and read from the device. This is
boonshen 0:a35c40f49345 134 * maximum of tx_length and rx_length.
boonshen 0:a35c40f49345 135 */
boonshen 0:a35c40f49345 136 virtual int write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length);
boonshen 0:a35c40f49345 137
boonshen 0:a35c40f49345 138 /** Acquire exclusive access to this SPI bus
boonshen 0:a35c40f49345 139 */
boonshen 0:a35c40f49345 140 virtual void lock(void);
boonshen 0:a35c40f49345 141
boonshen 0:a35c40f49345 142 /** Release exclusive access to this SPI bus
boonshen 0:a35c40f49345 143 */
boonshen 0:a35c40f49345 144 virtual void unlock(void);
boonshen 0:a35c40f49345 145
boonshen 0:a35c40f49345 146 /** Set default write data
boonshen 0:a35c40f49345 147 * SPI requires the master to send some data during a read operation.
boonshen 0:a35c40f49345 148 * Different devices may require different default byte values.
boonshen 0:a35c40f49345 149 * For example: A SD Card requires default bytes to be 0xFF.
boonshen 0:a35c40f49345 150 *
boonshen 0:a35c40f49345 151 * @param data Default character to be transmitted while read operation
boonshen 0:a35c40f49345 152 */
boonshen 0:a35c40f49345 153 void set_default_write_value(char data);
boonshen 0:a35c40f49345 154
boonshen 0:a35c40f49345 155 #if DEVICE_SPI_ASYNCH
boonshen 0:a35c40f49345 156
boonshen 0:a35c40f49345 157 /** Start non-blocking SPI transfer using 8bit buffers.
boonshen 0:a35c40f49345 158 *
boonshen 0:a35c40f49345 159 * This function locks the deep sleep until any event has occured
boonshen 0:a35c40f49345 160 *
boonshen 0:a35c40f49345 161 * @param tx_buffer The TX buffer with data to be transfered. If NULL is passed,
boonshen 0:a35c40f49345 162 * the default SPI value is sent
boonshen 0:a35c40f49345 163 * @param tx_length The length of TX buffer in bytes
boonshen 0:a35c40f49345 164 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
boonshen 0:a35c40f49345 165 * received data are ignored
boonshen 0:a35c40f49345 166 * @param rx_length The length of RX buffer in bytes
boonshen 0:a35c40f49345 167 * @param callback The event callback function
boonshen 0:a35c40f49345 168 * @param event The logical OR of events to modify. Look at spi hal header file for SPI events.
boonshen 0:a35c40f49345 169 * @return Zero if the transfer has started, or -1 if SPI peripheral is busy
boonshen 0:a35c40f49345 170 */
boonshen 0:a35c40f49345 171 template<typename Type>
boonshen 0:a35c40f49345 172 int transfer(const Type *tx_buffer, int tx_length, Type *rx_buffer, int rx_length, const event_callback_t& callback, int event = SPI_EVENT_COMPLETE) {
boonshen 0:a35c40f49345 173 if (spi_active(&_spi)) {
boonshen 0:a35c40f49345 174 return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, sizeof(Type)*8, callback, event);
boonshen 0:a35c40f49345 175 }
boonshen 0:a35c40f49345 176 start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, sizeof(Type)*8, callback, event);
boonshen 0:a35c40f49345 177 return 0;
boonshen 0:a35c40f49345 178 }
boonshen 0:a35c40f49345 179
boonshen 0:a35c40f49345 180 /** Abort the on-going SPI transfer, and continue with transfer's in the queue if any.
boonshen 0:a35c40f49345 181 */
boonshen 0:a35c40f49345 182 void abort_transfer();
boonshen 0:a35c40f49345 183
boonshen 0:a35c40f49345 184 /** Clear the transaction buffer
boonshen 0:a35c40f49345 185 */
boonshen 0:a35c40f49345 186 void clear_transfer_buffer();
boonshen 0:a35c40f49345 187
boonshen 0:a35c40f49345 188 /** Clear the transaction buffer and abort on-going transfer.
boonshen 0:a35c40f49345 189 */
boonshen 0:a35c40f49345 190 void abort_all_transfers();
boonshen 0:a35c40f49345 191
boonshen 0:a35c40f49345 192 /** Configure DMA usage suggestion for non-blocking transfers
boonshen 0:a35c40f49345 193 *
boonshen 0:a35c40f49345 194 * @param usage The usage DMA hint for peripheral
boonshen 0:a35c40f49345 195 * @return Zero if the usage was set, -1 if a transaction is on-going
boonshen 0:a35c40f49345 196 */
boonshen 0:a35c40f49345 197 int set_dma_usage(DMAUsage usage);
boonshen 0:a35c40f49345 198
boonshen 0:a35c40f49345 199 protected:
boonshen 0:a35c40f49345 200 /** SPI IRQ handler
boonshen 0:a35c40f49345 201 *
boonshen 0:a35c40f49345 202 */
boonshen 0:a35c40f49345 203 void irq_handler_asynch(void);
boonshen 0:a35c40f49345 204
boonshen 0:a35c40f49345 205 /** Common transfer method
boonshen 0:a35c40f49345 206 *
boonshen 0:a35c40f49345 207 * @param tx_buffer The TX buffer with data to be transfered. If NULL is passed,
boonshen 0:a35c40f49345 208 * the default SPI value is sent
boonshen 0:a35c40f49345 209 * @param tx_length The length of TX buffer in bytes
boonshen 0:a35c40f49345 210 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
boonshen 0:a35c40f49345 211 * received data are ignored
boonshen 0:a35c40f49345 212 * @param rx_length The length of RX buffer in bytes
boonshen 0:a35c40f49345 213 * @param bit_width The buffers element width
boonshen 0:a35c40f49345 214 * @param callback The event callback function
boonshen 0:a35c40f49345 215 * @param event The logical OR of events to modify
boonshen 0:a35c40f49345 216 * @return Zero if the transfer has started or was added to the queue, or -1 if SPI peripheral is busy/buffer is full
boonshen 0:a35c40f49345 217 */
boonshen 0:a35c40f49345 218 int 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);
boonshen 0:a35c40f49345 219
boonshen 0:a35c40f49345 220 /**
boonshen 0:a35c40f49345 221 *
boonshen 0:a35c40f49345 222 * @param tx_buffer The TX buffer with data to be transfered. If NULL is passed,
boonshen 0:a35c40f49345 223 * the default SPI value is sent
boonshen 0:a35c40f49345 224 * @param tx_length The length of TX buffer in bytes
boonshen 0:a35c40f49345 225 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
boonshen 0:a35c40f49345 226 * received data are ignored
boonshen 0:a35c40f49345 227 * @param rx_length The length of RX buffer in bytes
boonshen 0:a35c40f49345 228 * @param bit_width The buffers element width
boonshen 0:a35c40f49345 229 * @param callback The event callback function
boonshen 0:a35c40f49345 230 * @param event The logical OR of events to modify
boonshen 0:a35c40f49345 231 * @return Zero if a transfer was added to the queue, or -1 if the queue is full
boonshen 0:a35c40f49345 232 */
boonshen 0:a35c40f49345 233 int 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);
boonshen 0:a35c40f49345 234
boonshen 0:a35c40f49345 235 /** Configures a callback, spi peripheral and initiate a new transfer
boonshen 0:a35c40f49345 236 *
boonshen 0:a35c40f49345 237 * @param tx_buffer The TX buffer with data to be transfered. If NULL is passed,
boonshen 0:a35c40f49345 238 * the default SPI value is sent
boonshen 0:a35c40f49345 239 * @param tx_length The length of TX buffer in bytes
boonshen 0:a35c40f49345 240 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
boonshen 0:a35c40f49345 241 * received data are ignored
boonshen 0:a35c40f49345 242 * @param rx_length The length of RX buffer in bytes
boonshen 0:a35c40f49345 243 * @param bit_width The buffers element width
boonshen 0:a35c40f49345 244 * @param callback The event callback function
boonshen 0:a35c40f49345 245 * @param event The logical OR of events to modify
boonshen 0:a35c40f49345 246 */
boonshen 0:a35c40f49345 247 void 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);
boonshen 0:a35c40f49345 248
boonshen 0:a35c40f49345 249 #if TRANSACTION_QUEUE_SIZE_SPI
boonshen 0:a35c40f49345 250
boonshen 0:a35c40f49345 251 /** Start a new transaction
boonshen 0:a35c40f49345 252 *
boonshen 0:a35c40f49345 253 * @param data Transaction data
boonshen 0:a35c40f49345 254 */
boonshen 0:a35c40f49345 255 void start_transaction(transaction_t *data);
boonshen 0:a35c40f49345 256
boonshen 0:a35c40f49345 257 /** Dequeue a transaction
boonshen 0:a35c40f49345 258 *
boonshen 0:a35c40f49345 259 */
boonshen 0:a35c40f49345 260 void dequeue_transaction();
boonshen 0:a35c40f49345 261 static CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> _transaction_buffer;
boonshen 0:a35c40f49345 262 #endif
boonshen 0:a35c40f49345 263
boonshen 0:a35c40f49345 264 #endif
boonshen 0:a35c40f49345 265
boonshen 0:a35c40f49345 266 public:
boonshen 0:a35c40f49345 267 virtual ~SPI() {
boonshen 0:a35c40f49345 268 }
boonshen 0:a35c40f49345 269
boonshen 0:a35c40f49345 270 protected:
boonshen 0:a35c40f49345 271 spi_t _spi;
boonshen 0:a35c40f49345 272
boonshen 0:a35c40f49345 273 #if DEVICE_SPI_ASYNCH
boonshen 0:a35c40f49345 274 CThunk<SPI> _irq;
boonshen 0:a35c40f49345 275 event_callback_t _callback;
boonshen 0:a35c40f49345 276 DMAUsage _usage;
boonshen 0:a35c40f49345 277 #endif
boonshen 0:a35c40f49345 278
boonshen 0:a35c40f49345 279 void aquire(void);
boonshen 0:a35c40f49345 280 static SPI *_owner;
boonshen 0:a35c40f49345 281 static SingletonPtr<PlatformMutex> _mutex;
boonshen 0:a35c40f49345 282 int _bits;
boonshen 0:a35c40f49345 283 int _mode;
boonshen 0:a35c40f49345 284 int _hz;
boonshen 0:a35c40f49345 285 char _write_fill;
boonshen 0:a35c40f49345 286
boonshen 0:a35c40f49345 287 private:
boonshen 0:a35c40f49345 288 /* Private acquire function without locking/unlocking
boonshen 0:a35c40f49345 289 * Implemented in order to avoid duplicate locking and boost performance
boonshen 0:a35c40f49345 290 */
boonshen 0:a35c40f49345 291 void _acquire(void);
boonshen 0:a35c40f49345 292 };
boonshen 0:a35c40f49345 293
boonshen 0:a35c40f49345 294 } // namespace mbed
boonshen 0:a35c40f49345 295
boonshen 0:a35c40f49345 296 #endif
boonshen 0:a35c40f49345 297
boonshen 0:a35c40f49345 298 #endif