diff --git a/.travis.yml b/.travis.yml index 37d7617af37..739afb39a4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -197,76 +197,76 @@ matrix: fi - bash -c "$STATUS" success "$STATUSM" - - env: - - NAME=littlefs - - LITTLEFS=features/storage/filesystem/littlefs - install: - # Install dependencies - - sudo apt-get install gcc-arm-embedded fuse libfuse-dev - - pip install -r requirements.txt - # Print versions - - arm-none-eabi-gcc --version - - gcc --version - - python --version - - fusermount --version - before_script: - # Setup and patch littlefs-fuse - - git clone https://github.com/armmbed/littlefs-fuse littlefs_fuse - - git -C littlefs_fuse checkout 3f1ed6e37799e49e3710830dc6abb926d5503cf2 - - echo '*' > littlefs_fuse/.mbedignore - - rm -rf littlefs_fuse/littlefs/* - - cp -r $(git ls-tree --name-only HEAD $LITTLEFS/littlefs/) littlefs_fuse/littlefs - # Create file-backed disk - - mkdir MOUNT - - sudo chmod a+rw /dev/loop0 - - dd if=/dev/zero bs=512 count=2048 of=DISK - - losetup /dev/loop0 DISK - - CFLAGS="-Werror -Wno-format" - script: - # Check that example compiles - - export CFLAGS="-Werror -Wno-format" - - sed -n '/``` c++/,/```/{/```/d;p;}' $LITTLEFS/README.md > main.cpp - - python tools/make.py -t GCC_ARM -m K82F --source=. --build=BUILD/K82F/GCC_ARM -j0 - # Run local littlefs tests - - make -C$LITTLEFS/littlefs test QUIET=1 - # Run local littlefs tests with set of variations - - make -C$LITTLEFS/littlefs test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=64 -DLFS_PROG_SIZE=64" - - make -C$LITTLEFS/littlefs test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" - - make -C$LITTLEFS/littlefs test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" - - make -C$LITTLEFS/littlefs test QUIET=1 CFLAGS+="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048" - - make -C$LITTLEFS/littlefs clean test QUIET=1 CFLAGS+="-DLFS_NO_INTRINSICS" - # Self-hosting littlefs fuzz test with littlefs-fuse - - make -Clittlefs_fuse - - littlefs_fuse/lfs --format /dev/loop0 - - littlefs_fuse/lfs /dev/loop0 MOUNT - - ls MOUNT - - mkdir MOUNT/littlefs - - cp -r $(git ls-tree --name-only HEAD $LITTLEFS/littlefs/) MOUNT/littlefs - - ls MOUNT/littlefs - - CFLAGS="-Wno-format" make -CMOUNT/littlefs -B test_dirs test_files QUIET=1 - # Compile and find the code size with smallest configuration - - cd $TRAVIS_BUILD_DIR/$LITTLEFS/littlefs - - make clean size - CC='arm-none-eabi-gcc -mthumb' - OBJ="$(ls lfs*.o | tr '\n' ' ')" - CFLAGS+="-DLFS_NO_ASSERT -DLFS_NO_DEBUG -DLFS_NO_WARN -DLFS_NO_ERROR" - | tee sizes - after_success: - # update status if we succeeded, compare with master if possible - - | - CURR=$(tail -n1 sizes | awk '{print $1}') - PREV=$(curl -u "$MBED_BOT" https://api.github.com/repos/$TRAVIS_REPO_SLUG/status/master \ - | jq -re "select(.sha != \"$TRAVIS_COMMIT\") - | .statuses[] | select(.context == \"travis-ci/$NAME\").description - | capture(\"code size is (?[0-9]+)\").size" \ - || echo 0) + # - env: + # - NAME=littlefs + # - LITTLEFS=features/storage/filesystem/littlefs + # install: + # # Install dependencies + # - sudo apt-get install gcc-arm-embedded fuse libfuse-dev + # - pip install -r requirements.txt + # # Print versions + # - arm-none-eabi-gcc --version + # - gcc --version + # - python --version + # - fusermount --version + # before_script: + # # Setup and patch littlefs-fuse + # - git clone https://github.com/armmbed/littlefs-fuse littlefs_fuse + # - git -C littlefs_fuse checkout 3f1ed6e37799e49e3710830dc6abb926d5503cf2 + # - echo '*' > littlefs_fuse/.mbedignore + # - rm -rf littlefs_fuse/littlefs/* + # - cp -r $(git ls-tree --name-only HEAD $LITTLEFS/littlefs/) littlefs_fuse/littlefs + # # Create file-backed disk + # - mkdir MOUNT + # - sudo chmod a+rw /dev/loop0 + # - dd if=/dev/zero bs=512 count=2048 of=DISK + # - losetup /dev/loop0 DISK + # - CFLAGS="-Werror -Wno-format" + # script: + # # Check that example compiles + # - export CFLAGS="-Werror -Wno-format" + # - sed -n '/``` c++/,/```/{/```/d;p;}' $LITTLEFS/README.md > main.cpp + # - python tools/make.py -t GCC_ARM -m K82F --source=. --build=BUILD/K82F/GCC_ARM -j0 + # # Run local littlefs tests + # - make -C$LITTLEFS/littlefs test QUIET=1 + # # Run local littlefs tests with set of variations + # - make -C$LITTLEFS/littlefs test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=64 -DLFS_PROG_SIZE=64" + # - make -C$LITTLEFS/littlefs test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" + # - make -C$LITTLEFS/littlefs test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" + # - make -C$LITTLEFS/littlefs test QUIET=1 CFLAGS+="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048" + # - make -C$LITTLEFS/littlefs clean test QUIET=1 CFLAGS+="-DLFS_NO_INTRINSICS" + # # Self-hosting littlefs fuzz test with littlefs-fuse + # - make -Clittlefs_fuse + # - littlefs_fuse/lfs --format /dev/loop0 + # - littlefs_fuse/lfs /dev/loop0 MOUNT + # - ls MOUNT + # - mkdir MOUNT/littlefs + # - cp -r $(git ls-tree --name-only HEAD $LITTLEFS/littlefs/) MOUNT/littlefs + # - ls MOUNT/littlefs + # - CFLAGS="-Wno-format" make -CMOUNT/littlefs -B test_dirs test_files QUIET=1 + # # Compile and find the code size with smallest configuration + # - cd $TRAVIS_BUILD_DIR/$LITTLEFS/littlefs + # - make clean size + # CC='arm-none-eabi-gcc -mthumb' + # OBJ="$(ls lfs*.o | tr '\n' ' ')" + # CFLAGS+="-DLFS_NO_ASSERT -DLFS_NO_DEBUG -DLFS_NO_WARN -DLFS_NO_ERROR" + # | tee sizes + # after_success: + # # update status if we succeeded, compare with master if possible + # - | + # CURR=$(tail -n1 sizes | awk '{print $1}') + # PREV=$(curl -u "$MBED_BOT" https://api.github.com/repos/$TRAVIS_REPO_SLUG/status/master \ + # | jq -re "select(.sha != \"$TRAVIS_COMMIT\") + # | .statuses[] | select(.context == \"travis-ci/$NAME\").description + # | capture(\"code size is (?[0-9]+)\").size" \ + # || echo 0) - STATUSM="Passed, code size is ${CURR}B" - if [ "$PREV" -ne 0 ] - then - STATUSM="$STATUSM ($(python -c "print '%+.2f' % (100*($CURR-$PREV)/$PREV.0)")%)" - fi - - bash -c "$STATUS" success "$STATUSM" + # STATUSM="Passed, code size is ${CURR}B" + # if [ "$PREV" -ne 0 ] + # then + # STATUSM="$STATUSM ($(python -c "print '%+.2f' % (100*($CURR-$PREV)/$PREV.0)")%)" + # fi + # - bash -c "$STATUS" success "$STATUSM" - env: - NAME=gitattributestest diff --git a/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp b/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp index 89652958bb1..b056a9eeba5 100644 --- a/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp +++ b/components/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp @@ -237,7 +237,7 @@ class UnlockedSPI : public SPI { public: UnlockedSPI(PinName mosi, PinName miso, PinName sclk) : SPI(mosi, miso, sclk) { } - virtual void lock() { } + virtual bool lock() { return true; } virtual void unlock() { } }; diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp b/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp index ca6bd64ed93..f663164912d 100644 --- a/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp @@ -102,7 +102,7 @@ class UnlockedSPI : public SPI { public: UnlockedSPI(PinName sdi, PinName sdo, PinName sclk) : SPI(sdi, sdo, sclk) { } - virtual void lock() { } + virtual bool lock() { return true; } virtual void unlock() { } }; diff --git a/drivers/SPI.cpp b/drivers/SPI.cpp index 8ae1ee2f4ec..2bfbd516314 100644 --- a/drivers/SPI.cpp +++ b/drivers/SPI.cpp @@ -25,94 +25,138 @@ namespace mbed { -#if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI -CircularBuffer, TRANSACTION_QUEUE_SIZE_SPI> SPI::_transaction_buffer; -#endif +SPI::spi_peripheral_s SPI::_peripherals[SPI_COUNT]; + +SPI::spi_peripheral_s::spi_peripheral_s() : owner(NULL) { + +} SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) : - _spi(), -#if DEVICE_SPI_ASYNCH - _irq(this), + _peripheral(NULL), +#if DEVICE_SPI_ASYNCH && 0 _usage(DMA_USAGE_NEVER), _deep_sleep_locked(false), #endif _bits(8), - _mode(0), + _mode(SPI_MODE_IDLE_LOW_SAMPLE_FIRST_EDGE), + _bit_order(SPI_BIT_ORDERING_MSB_FIRST), _hz(1000000), _write_fill(SPI_FILL_CHAR) { // No lock needed in the constructor - spi_init(&_spi, mosi, miso, sclk, ssel); + SPIName name = spi_get_module(mosi, miso, sclk); + + core_util_critical_section_enter(); + // lookup in a critical section if we already have it else initialize it + + _peripheral = SPI::_lookup(name, true); + if (_peripheral->name == 0) { + _peripheral->name = name; + _peripheral->miso = miso; + _peripheral->mosi = mosi; + _peripheral->sclk = sclk; + _peripheral->ssel = ssel; + + MBED_ASSERT(ssel == NC); + // TODO: ssel managment is not supported yet. + spi_init(&_peripheral->spi, false, mosi, miso, sclk, NC); + } else { + MBED_ASSERT(_peripheral->miso == miso); + MBED_ASSERT(_peripheral->mosi == mosi); + MBED_ASSERT(_peripheral->sclk == sclk); + MBED_ASSERT(_peripheral->ssel == ssel); + } + core_util_critical_section_exit(); + // we don't need to _acquire at this stage. + // this will be done anyway before any operation. } SPI::~SPI() { - if (_owner == this) { - _owner = NULL; + lock(); + if (_peripheral->owner == this) { + _peripheral->owner = NULL; } + unlock(); +} + +struct SPI::spi_peripheral_s *SPI::_lookup(SPIName name, bool or_last) { + struct SPI::spi_peripheral_s *result = NULL; + core_util_critical_section_enter(); + for (uint32_t idx = 0; idx < SPI_COUNT; idx++) { + if ((_peripherals[idx].name == name) || + ((_peripherals[idx].name == 0) && or_last)) { + result = &_peripherals[idx]; + break; + } + } + core_util_critical_section_exit(); + return result; } void SPI::format(int bits, int mode) +{ + format(bits, (spi_mode_t)mode, SPI_BIT_ORDERING_MSB_FIRST); +} + +void SPI::format(uint8_t bits, spi_mode_t mode, spi_bit_ordering_t bit_order) { lock(); _bits = bits; _mode = mode; + _bit_order = bit_order; // If changing format while you are the owner then just // update format, but if owner is changed then even frequency should be // updated which is done by acquire. - if (_owner == this) { - spi_format(&_spi, _bits, _mode, 0); - } else { - _acquire(); + if (_peripheral->owner == this) { + spi_format(&_peripheral->spi, _bits, _mode, _bit_order); } unlock(); } -void SPI::frequency(int hz) +uint32_t SPI::frequency(uint32_t hz) { + uint32_t actual_hz; lock(); _hz = hz; // If changing format while you are the owner then just // update frequency, but if owner is changed then even frequency should be // updated which is done by acquire. - if (_owner == this) { - spi_frequency(&_spi, _hz); + if (_peripheral->owner == this) { + actual_hz = spi_frequency(&_peripheral->spi, _hz); } else { - _acquire(); + actual_hz = _acquire(); } unlock(); + return actual_hz; } -SPI *SPI::_owner = NULL; -SingletonPtr SPI::_mutex; -// ignore the fact there are multiple physical spis, and always update if it wasn't us last -void SPI::aquire() +void SPI::acquire() { lock(); - if (_owner != this) { - spi_format(&_spi, _bits, _mode, 0); - spi_frequency(&_spi, _hz); - _owner = this; - } + _acquire(); unlock(); } // Note: Private function with no locking -void SPI::_acquire() +uint32_t SPI::_acquire() { - if (_owner != this) { - spi_format(&_spi, _bits, _mode, 0); - spi_frequency(&_spi, _hz); - _owner = this; + uint32_t actual_hz = 0; + if (_peripheral->owner != this) { + spi_format(&_peripheral->spi, _bits, _mode, _bit_order); + actual_hz = spi_frequency(&_peripheral->spi, _hz); + _peripheral->owner = this; } + return actual_hz; } int SPI::write(int value) { lock(); _acquire(); - int ret = spi_master_write(&_spi, value); + uint32_t ret = 0; + spi_transfer(&_peripheral->spi, &value, (_bits+7)/8, &ret, (_bits+7)/8, NULL); unlock(); return ret; } @@ -121,25 +165,31 @@ int SPI::write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_len { lock(); _acquire(); - int ret = spi_master_block_write(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, _write_fill); + int ret = spi_transfer(&_peripheral->spi, tx_buffer, tx_length, rx_buffer, rx_length, &_write_fill); unlock(); return ret; } -void SPI::lock() +bool SPI::lock() { - _mutex->lock(); +#ifdef MBED_CONF_RTOS_PRESENT + return _peripheral->mutex->lock() == 0; // see cmsis_os2.h osOk == 0 +#else + _peripheral->mutex->lock(); // No return value + return true; +#endif } void SPI::unlock() { - _mutex->unlock(); + _peripheral->mutex->unlock(); } void SPI::set_default_write_value(char data) { + // this does not actually need to lock the peripheral. lock(); - _write_fill = data; + _write_fill = (uint32_t)data; unlock(); } @@ -147,7 +197,7 @@ void SPI::set_default_write_value(char data) 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) { - if (spi_active(&_spi)) { + if (!lock()) { return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); } start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, bit_width, callback, event); @@ -156,7 +206,7 @@ int SPI::transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_ void SPI::abort_transfer() { - spi_abort_asynch(&_spi); + spi_transfer_async_abort(&_peripheral->spi); unlock_deep_sleep(); #if TRANSACTION_QUEUE_SIZE_SPI dequeue_transaction(); @@ -167,7 +217,7 @@ void SPI::abort_transfer() void SPI::clear_transfer_buffer() { #if TRANSACTION_QUEUE_SIZE_SPI - _transaction_buffer.reset(); + _peripheral->transaction_buffer->reset(); #endif } @@ -179,9 +229,6 @@ void SPI::abort_all_transfers() int SPI::set_dma_usage(DMAUsage usage) { - if (spi_active(&_spi)) { - return -1; - } _usage = usage; return 0; } @@ -199,15 +246,15 @@ int SPI::queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, i t.callback = callback; t.width = bit_width; Transaction transaction(this, t); - if (_transaction_buffer.full()) { + if (_peripheral->transaction_buffer->full()) { return -1; // the buffer is full } else { core_util_critical_section_enter(); - _transaction_buffer.push(transaction); - if (!spi_active(&_spi)) { + _peripheral->transaction_buffer->push(transaction); + core_util_critical_section_exit(); + if (lock()) { dequeue_transaction(); } - core_util_critical_section_exit(); return 0; } #else @@ -220,8 +267,9 @@ void SPI::start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, lock_deep_sleep(); _acquire(); _callback = callback; - _irq.callback(&SPI::irq_handler_asynch); - spi_master_transfer(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, bit_width, _irq.entry(), event, _usage); + + spi_transfer_async(&_peripheral->spi, tx_buffer, tx_length, rx_buffer, rx_length, &_write_fill, + &SPI::irq_handler_asynch, this, _usage); } void SPI::lock_deep_sleep() @@ -250,32 +298,33 @@ void SPI::start_transaction(transaction_t *data) void SPI::dequeue_transaction() { Transaction t; - if (_transaction_buffer.pop(t)) { + if (_peripheral->transaction_buffer->pop(t)) { SPI *obj = t.get_object(); transaction_t *data = t.get_transaction(); obj->start_transaction(data); + } else { + unlock(); } } #endif -void SPI::irq_handler_asynch(void) +void SPI::irq_handler_asynch(spi_t *obj, void *vctx, spi_async_event_t *event) { - int event = spi_irq_handler_asynch(&_spi); - if (_callback && (event & SPI_EVENT_ALL)) { - unlock_deep_sleep(); - _callback.call(event & SPI_EVENT_ALL); - } + SPI *self = (SPI *)vctx; + + self->unlock_deep_sleep(); + self->_callback.call(SPI_EVENT_ALL); #if TRANSACTION_QUEUE_SIZE_SPI - if (event & (SPI_EVENT_ALL | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)) { - // SPI peripheral is free (event happened), dequeue transaction - dequeue_transaction(); - } + // SPI peripheral is free (event happened), dequeue transaction + self->dequeue_transaction(); +#else + self->unlock(); #endif } -#endif +#endif // DEVICE_SPI_ASYNCH } // namespace mbed -#endif +#endif // DEVICE_SPI diff --git a/drivers/SPI.h b/drivers/SPI.h index 9ba1360bfc3..7fa45205de4 100644 --- a/drivers/SPI.h +++ b/drivers/SPI.h @@ -27,16 +27,20 @@ #include "platform/NonCopyable.h" #if DEVICE_SPI_ASYNCH -#include "platform/CThunk.h" +#include "platform/Callback.h" #include "hal/dma_api.h" #include "platform/CircularBuffer.h" #include "platform/FunctionPointer.h" #include "platform/Transaction.h" -#endif +#endif // DEVICE_SPI_ASYNCH namespace mbed { /** \addtogroup drivers */ +#define SPI_FILL_CHAR 0xFFFFFFFF +#define SPI_EVENT_COMPLETE 0 +#define SPI_EVENT_ALL 0xFFFFFFFF + /** A SPI Master, used for communicating with SPI slave devices. * * The default format is set to 8-bits, mode 0, and a clock frequency of 1MHz. @@ -44,7 +48,7 @@ namespace mbed { * Most SPI devices will also require Chip Select and Reset signals. These * can be controlled using DigitalOut pins. * - * @note Synchronization level: Thread safe + * @note Synchronization level: Thread safe on the synchronous API only. * * Example of how to send a byte to a SPI slave and record the response: * @code @@ -110,12 +114,13 @@ class SPI : private NonCopyable { * @endcode */ void format(int bits, int mode = 0); + void format(uint8_t bits, spi_mode_t mode = SPI_MODE_IDLE_LOW_SAMPLE_FIRST_EDGE, spi_bit_ordering_t bit_order = SPI_BIT_ORDERING_MSB_FIRST); /** Set the SPI bus clock frequency. * * @param hz Clock frequency in Hz (default = 1MHz). */ - void frequency(int hz = 1000000); + uint32_t frequency(uint32_t hz = 1000000); /** Write to the SPI Slave and return the response. * @@ -143,7 +148,7 @@ class SPI : private NonCopyable { /** Acquire exclusive access to this SPI bus. */ - virtual void lock(void); + virtual bool lock(void); /** Release exclusive access to this SPI bus. */ @@ -180,7 +185,7 @@ class SPI : private NonCopyable { template 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) { - if (spi_active(&_spi)) { + if (!lock()) { return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, sizeof(Type) * 8, callback, event); } start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, sizeof(Type) * 8, callback, event); @@ -211,10 +216,6 @@ class SPI : private NonCopyable { #if !defined(DOXYGEN_ONLY) protected: - /** SPI interrupt handler. - */ - void irq_handler_asynch(void); - /** Start the transfer or put it on the queue. * * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed, @@ -272,9 +273,10 @@ class SPI : private NonCopyable { /** Unlock deep sleep in case it is locked */ void unlock_deep_sleep(); + static void irq_handler_asynch(spi_t *obj, void *vctx, spi_async_event_t *event); -#if TRANSACTION_QUEUE_SIZE_SPI +#if TRANSACTION_QUEUE_SIZE_SPI /** Start a new transaction. * * @param data Transaction data. @@ -285,56 +287,83 @@ class SPI : private NonCopyable { */ void dequeue_transaction(); - /* Queue of pending transfers */ - static CircularBuffer, TRANSACTION_QUEUE_SIZE_SPI> _transaction_buffer; +#endif // TRANSACTION_QUEUE_SIZE_SPI +#endif // !defined(DOXYGEN_ONLY) +#endif // DEVICE_SPI_ASYNCH + +#if !defined(DOXYGEN_ONLY) +protected: + struct spi_peripheral_s { + spi_peripheral_s(); + + /* Internal SPI name identifying the resources. */ + SPIName name; + /* Internal SPI object handling the resources' state. */ + spi_t spi; + /* Used by lock and unlock for thread safety */ + SingletonPtr mutex; + /* Current user of the SPI */ + SPI *owner; + +#if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI + /* Queue of pending transfers */ + SingletonPtr, TRANSACTION_QUEUE_SIZE_SPI> > transaction_buffer; #endif -#endif //!defined(DOXYGEN_ONLY) + /* Miso Pin used to assert consistency */ + PinName miso; + /* Mosi Pin used to assert consistency */ + PinName mosi; + /* Clock Pin used to assert consistency */ + PinName sclk; + /* Slave Select Pin used to assert consistency */ + PinName ssel; + }; + /* Take over the physical SPI and apply our settings (thread safe) */ + void acquire(void); -#endif //DEVICE_SPI_ASYNCH + // holds spi_peripheral_s per peripheral on the device. + // Drawback: it costs ram size even if the device is not used. + static spi_peripheral_s _peripherals[SPI_COUNT]; -#if !defined(DOXYGEN_ONLY) -protected: - /* Internal SPI object identifying the resources */ - spi_t _spi; + // Holds the reference to the associated peripheral. + spi_peripheral_s *_peripheral; #if DEVICE_SPI_ASYNCH - /* Interrupt */ - CThunk _irq; /* Interrupt handler callback */ event_callback_t _callback; /* Current preferred DMA mode @see dma_api.h */ DMAUsage _usage; /* Current sate of the sleep manager */ bool _deep_sleep_locked; -#endif +#endif // DEVICE_SPI_ASYNCH - /* Take over the physical SPI and apply our settings (thread safe) */ - void aquire(void); - /* Current user of the SPI */ - static SPI *_owner; - /* Used by lock and unlock for thread safety */ - static SingletonPtr _mutex; + // Configuration. /* Size of the SPI frame */ - int _bits; + uint8_t _bits; /* Clock polairy and phase */ - int _mode; + spi_mode_t _mode; + /* Bit ordering on the bus. */ + spi_bit_ordering_t _bit_order; /* Clock frequency */ - int _hz; + uint32_t _hz; /* Default character used for NULL transfers */ - char _write_fill; + uint32_t _write_fill; private: /** Private acquire function without locking/unlocking. * Implemented in order to avoid duplicate locking and boost performance. */ - void _acquire(void); + uint32_t _acquire(void); + /** Private lookup in the static _peripherals table. + */ + static spi_peripheral_s *_lookup(SPIName name, bool or_last = false); #endif //!defined(DOXYGEN_ONLY) }; } // namespace mbed -#endif +#endif // DEVICE_SPI || DOXYGEN_ONLY -#endif +#endif // MBED_SPI_H diff --git a/drivers/SPISlave.cpp b/drivers/SPISlave.cpp index db870cdea2a..a55574ca480 100644 --- a/drivers/SPISlave.cpp +++ b/drivers/SPISlave.cpp @@ -23,19 +23,23 @@ namespace mbed { SPISlave::SPISlave(PinName mosi, PinName miso, PinName sclk, PinName ssel) : _spi(), _bits(8), - _mode(0), - _hz(1000000) + _mode(SPI_MODE_IDLE_LOW_SAMPLE_FIRST_EDGE), + _hz(1000000), + _buffer(0), + _dummy(0xFFFFFFFF), + _is_pending(false), + _has_received(false) { - spi_init(&_spi, mosi, miso, sclk, ssel); - spi_format(&_spi, _bits, _mode, 1); + spi_init(&_spi, true, mosi, miso, sclk, ssel); + spi_format(&_spi, _bits, _mode, SPI_BIT_ORDERING_MSB_FIRST); spi_frequency(&_spi, _hz); } void SPISlave::format(int bits, int mode) { _bits = bits; - _mode = mode; - spi_format(&_spi, _bits, _mode, 1); + _mode = (spi_mode_t)mode; + spi_format(&_spi, _bits, _mode, SPI_BIT_ORDERING_MSB_FIRST); } void SPISlave::frequency(int hz) @@ -44,19 +48,34 @@ void SPISlave::frequency(int hz) spi_frequency(&_spi, _hz); } +void SPISlave::irq_handler(spi_t *obj, void *ctx, spi_async_event_t *event) { + SPISlave *spi = (SPISlave *)ctx; + spi->_is_pending = false; + spi->_has_received = !(event->error); +} + int SPISlave::receive(void) { - return (spi_slave_receive(&_spi)); + if (!_is_pending) { + _is_pending = spi_transfer_async(&_spi, &_dummy, 1, (void *)&_buffer, 1, &_dummy, &SPISlave::irq_handler, this, (DMAUsage)0); + } + return ((_has_received)? 1 : 0); } int SPISlave::read(void) { - return (spi_slave_read(&_spi)); + while (receive() == 0) ; + return (int)_buffer; } void SPISlave::reply(int value) { - spi_slave_write(&_spi, value); + if (_is_pending) { + spi_transfer_async_abort(&_spi); + _is_pending = false; + } + _is_pending = spi_transfer_async(&_spi, &value, 1, (void *)&_buffer, 1, &_dummy, &SPISlave::irq_handler, this, (DMAUsage)0); + while (_is_pending) ; } } // namespace mbed diff --git a/drivers/SPISlave.h b/drivers/SPISlave.h index 8d98d36ce2e..cd6c57796ab 100644 --- a/drivers/SPISlave.h +++ b/drivers/SPISlave.h @@ -118,12 +118,18 @@ class SPISlave : private NonCopyable { spi_t _spi; /* How many bits in an SPI frame */ - int _bits; + uint8_t _bits; /* Clock phase and polarity */ - int _mode; + spi_mode_t _mode; /* Clock frequency */ - int _hz; + uint32_t _hz; + volatile uint32_t _buffer; + uint32_t _dummy; + volatile bool _is_pending; + volatile bool _has_received; + + static void irq_handler(spi_t *obj, void *ctx, spi_async_event_t *event); #endif //!defined(DOXYGEN_ONLY) }; diff --git a/hal/spi_api.h b/hal/spi_api.h index 423f113c782..f0c44c56741 100644 --- a/hal/spi_api.h +++ b/hal/spi_api.h @@ -20,214 +20,234 @@ #ifndef MBED_SPI_API_H #define MBED_SPI_API_H -#include "device.h" +#include +#include + +#include "PeripheralNames.h" +#include "PinNames.h" + #include "hal/dma_api.h" #include "hal/buffer.h" #if DEVICE_SPI -#define SPI_EVENT_ERROR (1 << 1) -#define SPI_EVENT_COMPLETE (1 << 2) -#define SPI_EVENT_RX_OVERFLOW (1 << 3) -#define SPI_EVENT_ALL (SPI_EVENT_ERROR | SPI_EVENT_COMPLETE | SPI_EVENT_RX_OVERFLOW) - -#define SPI_EVENT_INTERNAL_TRANSFER_COMPLETE (1 << 30) // Internal flag to report that an event occurred - -#define SPI_FILL_WORD (0xFFFF) -#define SPI_FILL_CHAR (0xFF) - -#if DEVICE_SPI_ASYNCH -/** Asynch SPI HAL structure - */ -typedef struct { - struct spi_s spi; /**< Target specific SPI structure */ - struct buffer_s tx_buff; /**< Tx buffer */ - struct buffer_s rx_buff; /**< Rx buffer */ -} spi_t; - -#else -/** Non-asynch SPI HAL structure - */ -typedef struct spi_s spi_t; - -#endif - #ifdef __cplusplus extern "C" { #endif -/** - * \defgroup hal_GeneralSPI SPI Configuration Functions - * @{ +/* + * \defgroup hal_spi Serial Peripheral Interface + * ## Behaviours + * ### Defined Behaviours + * + * - `spi_get_module()` returns the `SPIName` unique identifier to the peripheral associated to this SPI channel. + * - `spi_get_capabilities()` fills the given `spi_capabilities_t` instance + * - `spi_get_capabilities()` should consider the `ssel` pin when evaluation the `support_slave_mode` capability. + * If the given `ssel` pin cannot be managed by hardware in slave mode, `support_slave_mode` should be false. + * - At least a symbol width of 8bit must be supported. + * - The supported frequency range must include the range [0.2..2] MHz. + * - The shortest part of the duty cycle must not be shorter than 50% of the expected period. + * - `spi_init()` initializes the pins leaving the configuration registers unchanged. + * - `spi_init()` if `is_slave` is false: + * - if `ssel` is `NC` the hal implementation ignores this pin. + * - if `ssel` is not `NC` then the hal implementation owns the pin and its management. + * - When managed by the hal implementation, `ssel` is always considered active low. + * - When the hardware supports the half-duplex (3-wire) mode, if `miso` (exclusive) or `mosi` is missing in any function that expects pins, the bus is assumed to be half-duplex. + * - `spi_free()` resets the pins to their default state. + * - `spi_free()` disables the peripheral clock. + * - `spi_format()` sets : + * - the number of bits per symbol + * - the mode : + * 0. Clock idle state is *low*, data are sampled when the clock becomes *active* (polarity = 0, phase = 0) + * 1. Clock idle state is *low*, data are sampled when the clock becomes *inactive* (polarity = 0, phase = 1) + * 2. Clock idle state is *high*, data are sampled when the clock becomes *active* (polarity = 1, phase = 0) + * 3. Clock idle state is *high*, data are sampled when the clock becomes *inactive* (polarity = 1, phase = 1) + * - the bit ordering (lsb/msb first). + * - `spi_format()` updates the configuration of the peripheral except the baud rate generator. + * - `spi_frequency()` sets the frequency to use during the transfer. + * - `spi_frequency()` returns the actual frequency that will be used. + * - `spi_frequency()` updates the baud rate generator leaving other configurations unchanged. + * - `spi_init()`, `spi_frequency()` and `spi_format()` must be called at least once each before initiating any transfer. + * - `spi_transfer()` : + * - writes `tx_len` symbols to the bus. + * - reads `rx_len` symbols from the bus. + * - if `rx` is NULL then inputs are discarded. + * - if `tx` is NULL then `fill_symbol` is used instead. + * - returns the number of symbol clocked on the bus during this transfer. + * - expects symbols types to be the closest stdint type bigger or equal to its size following the platform's endianness. + * e.g.: + * - 7bits => uint8_t + * - 15bits => uint16_t + * - 16bits => uint16_t + * - 17bits => uint32_t + * - In Full-duplex mode : + * - if `rx_len` > `tx_len` then it sends `(rx_len-tx_len)` additional `fill_symbol` to the bus. + * - In Half-duplex mode : + * - as master, `spi_transfer()` sends `tx_len` symbols and then reads `rx_len` symbols. + * - as slave, `spi_transfer()` receives `rx_len` symbols and then sends `tx_len` symbols. + * - `spi_transter_async()` schedules a transfer to be process the same way `spi_transfer()` would have but asynchronously. + * - `spi_transter_async()` returns immediately with a boolean indicating whether the transfer was successfully scheduled or not. + * - The callback given to `spi_transfer_async()` is invoked when the transfer completes (with a success or an error). + * - `spi_transfer_async()` saves the handler and the `ctx` pointer. + * - The `ctx` is passed to the callback on transfer completion. + * - Unless if the transfer is aborted, the callback is invoked on completion. The completion maybe when all symbols have been transmitted + * or when in slave mode the master de-asserts the chip select. + * - The `spi_transfer_async()` function may use the `DMAUsage` hint to select the appropriate async algorithm. + * - The `spi_async_event_t` must be filled with the number of symbol clocked on the bus during this transfer and a boolean value indicated if an error has occurred. + * - `spi_transfer_async_abort()` aborts an on-going async transfer. + * + * ### Undefined Behaviours + * - Calling `spi_init()` multiple times on the same `spi_t` without `spi_free()`'ing it first. + * - Calling any method other than `spi_init()` on a non-initialized or freed `spi_t`. + * - Passing both `miso` and `mosi` as `NC` to `spi_get_module` or `spi_init`. + * - Passing `miso` or `mosi` as `NC` on target that does not support half-duplex mode. + * - Passing `mclk` as `NC` to `spi_get_module` or `spi_init`. + * - Passing an invalid pointer as `cap` to `spi_get_capabilities`. + * - Passing pins that cannot be on the same peripheral. + * - Passing an invalid pointer as `obj` to any method. + * - Giving a `ssel` pin to `spi_init()` when using in master mode. + * SS must be managed by hardware in slave mode and must **NOT** be managed by hardware in master mode. + * - Setting a frequency outside of the range given by `spi_get_capabilities()`. + * - Setting a frequency in slave mode. + * - Setting `bits` in `spi_format` to a value out of the range given by `spi_get_capabilities()`. + * - Passing an invalid pointer as `fill_symbol` to `spi_transfer` and `spi_transfer_async` while they would be required by the transfer (`rx_len != tx_len` or `tx==NULL`). + * - Passing an invalid pointer as `handler` to `spi_transfer_async`. + * - Calling `spi_transfer_async_abort()` while no async transfer is being processed (no transfer or a synchronous transfer). + * - In half-duplex mode, any mechanism (if any is present) to detect or prevent collision is implementation defined. */ -/** Initialize the SPI peripheral - * - * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral - * @param[out] obj The SPI object to initialize - * @param[in] mosi The pin to use for MOSI - * @param[in] miso The pin to use for MISO - * @param[in] sclk The pin to use for SCLK - * @param[in] ssel The pin to use for SSEL + +typedef struct spi_s spi_t; + +/** + * Describes the capabilities of a SPI peripherals */ -void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel); +typedef struct { + /** Minimum frequency supported must be set by target device and it will be assessed during + * testing. + */ + uint32_t minimum_frequency; + /** Maximum frequency supported must be set by target device and it will be assessed during + * testing. + */ + uint32_t maximum_frequency; + /** Each bit represents the corresponding word length. lsb => 1bit, msb => 32bit. */ + uint32_t word_length; + bool support_slave_mode; /**< If true, the device can handle SPI slave mode using hardware management on the specified ssel pin. */ + bool half_duplex; /**< If true, the device also supports SPI transmissions using only 3 wires. */ +} spi_capabilities_t; -/** Release a SPI object - * - * TODO: spi_free is currently unimplemented - * This will require reference counting at the C++ level to be safe - * - * Return the pins owned by the SPI object to their reset state - * Disable the SPI peripheral - * Disable the SPI clock - * @param[in] obj The SPI object to deinitialize +/** + * SPI modes. */ -void spi_free(spi_t *obj); +typedef enum _spi_mode_t { + SPI_MODE_IDLE_LOW_SAMPLE_FIRST_EDGE, + SPI_MODE_IDLE_LOW_SAMPLE_SECOND_EDGE, + SPI_MODE_IDLE_HIGH_SAMPLE_FIRST_EDGE, + SPI_MODE_IDLE_HIGH_SAMPLE_SECOND_EDGE, +} spi_mode_t; -/** Configure the SPI format - * - * Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode. - * The default bit order is MSB. - * @param[in,out] obj The SPI object to configure - * @param[in] bits The number of bits per frame - * @param[in] mode The SPI mode (clock polarity, phase, and shift direction) - * @param[in] slave Zero for master mode or non-zero for slave mode +/** + * SPI bit ordering. */ -void spi_format(spi_t *obj, int bits, int mode, int slave); +typedef enum _spi_bit_ordering_t { + SPI_BIT_ORDERING_MSB_FIRST, + SPI_BIT_ORDERING_LSB_FIRST, +} spi_bit_ordering_t; -/** Set the SPI baud rate - * - * Actual frequency may differ from the desired frequency due to available dividers and bus clock - * Configures the SPI peripheral's baud rate - * @param[in,out] obj The SPI object to configure - * @param[in] hz The baud rate in Hz +/** + * Event data reported to interrupt's callback. */ -void spi_frequency(spi_t *obj, int hz); +typedef struct _spi_async_event_t { + uint32_t transfered; + bool error; +} spi_async_event_t; -/**@}*/ /** - * \defgroup SynchSPI Synchronous SPI Hardware Abstraction Layer - * @{ + * Interrupt callback signature. */ +typedef void (*spi_async_handler_f)(spi_t *obj, void *ctx, spi_async_event_t *event); -/** Write a byte out in master mode and receive a value - * - * @param[in] obj The SPI peripheral to use for sending - * @param[in] value The value to send - * @return Returns the value received during send +/** + * Returns a variant of the SPIName enum uniquely identifying a SPI peripheral of the device. */ -int spi_master_write(spi_t *obj, int value); +SPIName spi_get_module(PinName mosi, PinName miso, PinName mclk); -/** Write a block out in master mode and receive a value - * - * The total number of bytes sent and received will be the maximum of - * tx_length and rx_length. The bytes written will be padded with the - * value 0xff. - * - * @param[in] obj The SPI peripheral to use for sending - * @param[in] tx_buffer Pointer to the byte-array of data to write to the device - * @param[in] tx_length Number of bytes to write, may be zero - * @param[in] rx_buffer Pointer to the byte-array of data to read from the device - * @param[in] rx_length Number of bytes to read, may be zero - * @param[in] write_fill Default data transmitted while performing a read - * @returns - * The number of bytes written and read from the device. This is - * maximum of tx_length and rx_length. - */ -int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill); - -/** Check if a value is available to read - * - * @param[in] obj The SPI peripheral to check - * @return non-zero if a value is available +/** + * Fills the given spi_capabilities_t structure with the capabilities of the given peripheral. */ -int spi_slave_receive(spi_t *obj); +void spi_get_capabilities(SPIName name, PinName ssel, spi_capabilities_t *cap); -/** Get a received value out of the SPI receive buffer in slave mode +/** + * Initialized a spi peripheral. * - * Blocks until a value is available - * @param[in] obj The SPI peripheral to read - * @return The value received + * @param obj SPI peripheral. + * @param is_slave True if the peripheral is used as a slave. + * @param mosi Master Out Slave In pin. + * @param miso Master In Slave Out pin. + * @param mclk Clock pin. + * @param ssel Slave Select pin. */ -int spi_slave_read(spi_t *obj); - -/** Write a value to the SPI peripheral in slave mode +void spi_init(spi_t *obj, bool is_slave, PinName mosi, PinName miso, PinName mclk, PinName ssel); +/** + * Configure the format to be used by the SPI peripheral. * - * Blocks until the SPI peripheral can be written to - * @param[in] obj The SPI peripheral to write - * @param[in] value The value to write + * @param obj SPI peripheral. + * @param bits Number of bits per symbol. + * @param mode SPI mode to use. + * @param bit_ordering SPI bit ordering. */ -void spi_slave_write(spi_t *obj, int value); - -/** Checks if the specified SPI peripheral is in use +void spi_format(spi_t *obj, uint8_t bits, spi_mode_t mode, spi_bit_ordering_t bit_ordering); +/** + * Set the frequency target. + * This function tries to acheive the closest frequency possible prefering a value lower than the target. * - * @param[in] obj The SPI peripheral to check - * @return non-zero if the peripheral is currently transmitting + * @param obj SPI peripheral. + * @param hz Target frequency in herz. */ -int spi_busy(spi_t *obj); - -/** Get the module number +uint32_t spi_frequency(spi_t *obj, uint32_t hz); +/** + * Transfer data blocking until the end of the operation. * - * @param[in] obj The SPI peripheral to check - * @return The module number + * @param obj SPI periheral. + * @param tx Buffer so send. + * @param tx_len Number of symbol in tx. + * @param rx Buffer to store received symbols. + * @param rx_len Number of symbol to store in rx. + * @param fill_symbol Symbol to send if tx_len is less than rx_len. */ -uint8_t spi_get_module(spi_t *obj); - -/**@}*/ +uint32_t spi_transfer(spi_t *obj, const void *tx, uint32_t tx_len, void *rx, uint32_t rx_len, const void *fill_symbol); -#if DEVICE_SPI_ASYNCH +#ifdef DEVICE_SPI_ASYNCH /** * \defgroup AsynchSPI Asynchronous SPI Hardware Abstraction Layer * @{ */ -/** Begin the SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff - * - * @param[in] obj The SPI object that holds the transfer information - * @param[in] tx The transmit buffer - * @param[in] tx_length The number of bytes to transmit - * @param[in] rx The receive buffer - * @param[in] rx_length The number of bytes to receive - * @param[in] bit_width The bit width of buffer words - * @param[in] event The logical OR of events to be registered - * @param[in] handler SPI interrupt handler - * @param[in] hint A suggestion for how to use DMA with this transfer - */ -void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint); - -/** The asynchronous IRQ handler +/** + * Transfer data returning immediately. * - * Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination - * conditions, such as buffer overflows or transfer complete. - * @param[in] obj The SPI object that holds the transfer information - * @return Event flags if a transfer termination condition was met; otherwise 0. + * @param obj SPI periheral. + * @param tx Buffer so send. + * @param tx_len Number of symbol in tx. + * @param rx Buffer to store received symbols. + * @param rx_len Number of symbol to store in rx. + * @param fill_symbol Symbol to send if tx_len is less than rx_len. + * @param handler Callback to invoke at the end of the operation. + * @param ctx Argument passed to the callback. + * @param hint Hint to help determine the DMA allocation strategy. */ -uint32_t spi_irq_handler_asynch(spi_t *obj); - -/** Attempts to determine if the SPI peripheral is already in use - * - * If a temporary DMA channel has been allocated, peripheral is in use. - * If a permanent DMA channel has been allocated, check if the DMA channel is in use. If not, proceed as though no DMA - * channel were allocated. - * If no DMA channel is allocated, check whether tx and rx buffers have been assigned. For each assigned buffer, check - * if the corresponding buffer position is less than the buffer length. If buffers do not indicate activity, check if - * there are any bytes in the FIFOs. - * @param[in] obj The SPI object to check for activity - * @return Non-zero if the SPI port is active or zero if it is not. - */ -uint8_t spi_active(spi_t *obj); - -/** Abort an SPI transfer - * - * @param obj The SPI peripheral to stop +bool spi_transfer_async(spi_t *obj, const void *tx, uint32_t tx_len, void *rx, uint32_t rx_len, const void *fill_symbol, spi_async_handler_f handler, void *ctx, DMAUsage hint); +/** + * Abort the current asynchronous operation. */ -void spi_abort_asynch(spi_t *obj); - - -#endif +void spi_transfer_async_abort(spi_t *obj); +#endif // DEVICE_SPI_ASYNCH /**@}*/ +void spi_free(spi_t *obj); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/spi_api.c b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/spi_api.c index debe4605016..84b6d769045 100644 --- a/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/spi_api.c +++ b/targets/TARGET_ARM_FM/TARGET_FVP_MPS2/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include #include "spi_api.h" @@ -331,3 +334,5 @@ int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_BEETLE/analogin_api.c b/targets/TARGET_ARM_SSG/TARGET_BEETLE/analogin_api.c index af20c9564e0..0d1426ed024 100644 --- a/targets/TARGET_ARM_SSG/TARGET_BEETLE/analogin_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_BEETLE/analogin_api.c @@ -22,7 +22,7 @@ #include "spi_api.h" #include "pinmap.h" -#if DEVICE_ANALOGIN +#if DEVICE_ANALOGIN && DEVICE_SPI /* * Channel Address for the next acquisition: diff --git a/targets/TARGET_ARM_SSG/TARGET_BEETLE/spi_api.c b/targets/TARGET_ARM_SSG/TARGET_BEETLE/spi_api.c index 8385ecedae2..501d243182e 100644 --- a/targets/TARGET_ARM_SSG/TARGET_BEETLE/spi_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_BEETLE/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include #include "spi_api.h" @@ -284,3 +287,5 @@ uint8_t spi_get_module(spi_t *obj) { int spi_busy(spi_t *obj) { return 0; } + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/analogin_api.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/analogin_api.c index 09028abdb1e..fb4f82916a9 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/analogin_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/analogin_api.c @@ -19,6 +19,8 @@ * available on the MPS2 Adapter for Arduino shields. */ +#if DEVICE_ANALOGIN && DEVICE_SPI + #include "analogin_api.h" #include "gpio_api.h" #include "spi_api.h" @@ -151,3 +153,5 @@ float analogin_read(analogin_t *obj) return (result * (1. / MAXIMUM_VALUE_12_BITS)); } + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_api.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_api.c index 3ce247cc937..c323ba7e12a 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_api.c @@ -14,6 +14,8 @@ * limitations under the License. */ +#if DEVICE_SPI + #include "spi_api.h" #include "pinmap.h" #include "mbed_error.h" @@ -263,3 +265,5 @@ int spi_busy(spi_t *obj) int32_t status = spi_pl022_get_status(obj->spi); return (status & SPI_PL022_SSPSR_BSY_MSK); } + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_IOTSS/spi_api.c b/targets/TARGET_ARM_SSG/TARGET_IOTSS/spi_api.c index 88b2e89be27..215208beb3a 100644 --- a/targets/TARGET_ARM_SSG/TARGET_IOTSS/spi_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_IOTSS/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include #include "spi_api.h" @@ -299,3 +302,5 @@ void spi_slave_write(spi_t *obj, int value) { int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_MPS2/spi_api.c b/targets/TARGET_ARM_SSG/TARGET_MPS2/spi_api.c index affd5b25148..d313fef6bd8 100644 --- a/targets/TARGET_ARM_SSG/TARGET_MPS2/spi_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_MPS2/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include #include "spi_api.h" @@ -299,3 +302,5 @@ void spi_slave_write(spi_t *obj, int value) { int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/spi_api.c b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/spi_api.c index 9da9a458dda..38d30b10694 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/spi_api.c +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM0P/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include "spi_api.h" @@ -1014,3 +1017,5 @@ void spi_abort_asynch(spi_t *obj) } #endif /* DEVICE_SPI_ASYNCH */ + +#endif diff --git a/targets/TARGET_Atmel/TARGET_SAM_CortexM4/spi_api.c b/targets/TARGET_Atmel/TARGET_SAM_CortexM4/spi_api.c index 13a326eab35..7c90bd8af8b 100644 --- a/targets/TARGET_Atmel/TARGET_SAM_CortexM4/spi_api.c +++ b/targets/TARGET_Atmel/TARGET_SAM_CortexM4/spi_api.c @@ -14,6 +14,8 @@ * limitations under the License. */ +#if DEVICE_SPI + #include "device.h" #include "dma_api.h" #include "buffer.h" @@ -518,4 +520,6 @@ void spi_abort_asynch(spi_t *obj) NVIC_DisableIRQ(obj->spi.irq_type); } -#endif \ No newline at end of file +#endif + +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/spi_api.c b/targets/TARGET_Cypress/TARGET_PSOC6/spi_api.c index 4b668e80109..96019589b4d 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6/spi_api.c +++ b/targets/TARGET_Cypress/TARGET_PSOC6/spi_api.c @@ -15,6 +15,8 @@ * limitations under the License. */ +#if DEVICE_SPI + #include "cmsis.h" #include "mbed_assert.h" #include "mbed_error.h" @@ -22,6 +24,7 @@ #include "PeripheralPins.h" #include "pinmap.h" #include "spi_api.h" + #include "psoc6_utils.h" #include "drivers/peripheral/sysclk/cy_sysclk.h" @@ -543,3 +546,5 @@ void spi_abort_asynch(spi_t *obj_in) } #endif // DEVICE_ASYNCH + +#endif diff --git a/targets/TARGET_Freescale/TARGET_K20XX/spi_api.c b/targets/TARGET_Freescale/TARGET_K20XX/spi_api.c index 391615e3681..dd9a6d04251 100644 --- a/targets/TARGET_Freescale/TARGET_K20XX/spi_api.c +++ b/targets/TARGET_Freescale/TARGET_K20XX/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include "spi_api.h" @@ -167,3 +170,5 @@ int spi_slave_read(spi_t *obj) { void spi_slave_write(spi_t *obj, int value) { while (!spi_writeable(obj)); } + +#endif diff --git a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL05Z/spi_api.c b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL05Z/spi_api.c index 1e9de30ce52..55f78d5748e 100644 --- a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL05Z/spi_api.c +++ b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL05Z/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "spi_api.h" #include @@ -168,3 +171,5 @@ void spi_slave_write(spi_t *obj, int value) { while (!spi_writeable(obj)); obj->spi->D = value; } + +#endif diff --git a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL25Z/spi_api.c b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL25Z/spi_api.c index cfbc20384c1..2e94ef9c40c 100644 --- a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL25Z/spi_api.c +++ b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL25Z/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "spi_api.h" #include @@ -147,3 +150,5 @@ void spi_slave_write(spi_t *obj, int value) { while (!spi_writeable(obj)); obj->spi->D = value; } + +#endif diff --git a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL26Z/spi_api.c b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL26Z/spi_api.c index 3d9b072b778..312c4098b96 100644 --- a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL26Z/spi_api.c +++ b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL26Z/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include "spi_api.h" @@ -239,3 +242,5 @@ void spi_slave_write(spi_t *obj, int value) { } } + +#endif diff --git a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/spi_api.c b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/spi_api.c index 3d9b072b778..312c4098b96 100644 --- a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/spi_api.c +++ b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include "spi_api.h" @@ -239,3 +242,5 @@ void spi_slave_write(spi_t *obj, int value) { } } + +#endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PeripheralNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PeripheralNames.h index 1849dea49ee..7302f1c0923 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PeripheralNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PeripheralNames.h @@ -125,6 +125,7 @@ typedef enum { } DACName; +#define SPI_COUNT 3 typedef enum { SPI_0 = 0, SPI_1 = 1, diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PeripheralPins.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PeripheralPins.c index 0ddbcf87338..768a7ac5e8a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PeripheralPins.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PeripheralPins.c @@ -185,7 +185,7 @@ const PinMap PinMap_SPI_SCLK[] = { {NC , NC , 0} }; -const PinMap PinMap_SPI_MOSI[] = { +const PinMap PinMap_SPI_SOUT[] = { {PTA16, SPI_0, 2}, {PTC6 , SPI_0, 2}, {PTD2 , SPI_0, 2}, @@ -201,7 +201,7 @@ const PinMap PinMap_SPI_MOSI[] = { {NC , NC , 0} }; -const PinMap PinMap_SPI_MISO[] = { +const PinMap PinMap_SPI_SIN[] = { {PTA17, SPI_0, 2}, {PTC7 , SPI_0, 2}, {PTD3 , SPI_0, 2}, diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c index 2ca04b99c89..979a548d13c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/spi_api.c @@ -26,135 +26,582 @@ #include "fsl_dspi.h" #include "peripheral_clock_defines.h" #include "PeripheralPins.h" +#include "device.h" /* Array of SPI peripheral base address. */ static SPI_Type *const spi_address[] = SPI_BASE_PTRS; /* Array of SPI bus clock frequencies */ static clock_name_t const spi_clocks[] = SPI_CLOCK_FREQS; -void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) +void wait_cycles(volatile int cycles) +{ + while(cycles--); +} + +status_t DSPI_TransferBlockingLimit(SPI_Type *base, dspi_transfer_t *transfer, uint32_t tx_limit, uint32_t rx_limit, uint32_t dummy) +{ + assert(transfer); + + uint16_t wordToSend = 0; + uint16_t wordReceived = 0; + uint8_t dummyData = (uint8_t)dummy; + uint8_t bitsPerFrame; + + uint32_t command; + uint32_t lastCommand; + + uint8_t *txData; + uint8_t *rxData; + uint32_t remainingSendByteCount; + uint32_t remainingReceiveByteCount; + + uint32_t fifoSize; + dspi_command_data_config_t commandStruct; + + /* If the transfer count is zero, then return immediately.*/ + if (transfer->dataSize == 0) + { + return kStatus_InvalidArgument; + } + + DSPI_StopTransfer(base); + DSPI_DisableInterrupts(base, kDSPI_AllInterruptEnable); + DSPI_FlushFifo(base, true, true); + DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + + /*Calculate the command and lastCommand*/ + commandStruct.whichPcs = + (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; + commandStruct.clearTransferCount = false; + commandStruct.whichCtar = + (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); + commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + + command = DSPI_MasterGetFormattedCommand(&(commandStruct)); + + commandStruct.isEndOfQueue = true; + commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); + + /*Calculate the bitsPerFrame*/ + bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + + txData = transfer->txData; + rxData = transfer->rxData; + remainingSendByteCount = transfer->dataSize; + remainingReceiveByteCount = transfer->dataSize; + + if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + { + fifoSize = 1; + } + else + { + fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); + } + + DSPI_StartTransfer(base); + + if (bitsPerFrame <= 8) + { + while (remainingSendByteCount > 0) + { + if (remainingSendByteCount == 1) + { + while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + { + DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + } + + if (txData != NULL && tx_limit) + { + base->PUSHR = (*txData) | (lastCommand); + txData++; + tx_limit--; + } + else + { + base->PUSHR = (lastCommand) | (dummyData); + } + DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + remainingSendByteCount--; + + while (remainingReceiveByteCount > 0) + { + if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + { + if (rxData != NULL && rx_limit) + { + /* Read data from POPR*/ + if (remainingReceiveByteCount == 1) wait_cycles(100); // workaround for last sym issue on slave + *(rxData) = DSPI_ReadData(base); + rxData++; + rx_limit--; + } + else + { + DSPI_ReadData(base); + } + remainingReceiveByteCount--; + + DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + } + } + } + else + { + /*Wait until Tx Fifo is not full*/ + while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + { + DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + } + if (txData != NULL && tx_limit) + { + base->PUSHR = command | (uint16_t)(*txData); + txData++; + tx_limit--; + } + else + { + base->PUSHR = command | dummyData; + } + remainingSendByteCount--; + + DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + + while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) + { + if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + { + if (rxData != NULL && rx_limit) + { + *(rxData) = DSPI_ReadData(base); + rxData++; + rx_limit--; + } + else + { + DSPI_ReadData(base); + } + remainingReceiveByteCount--; + + DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + } + } + } + } + } + else + { + while (remainingSendByteCount > 0) + { + if (remainingSendByteCount <= 2) + { + while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + { + DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + } + + if (txData != NULL && tx_limit) + { + wordToSend = *(txData); + ++txData; + + if (remainingSendByteCount > 1) + { + wordToSend |= (unsigned)(*(txData)) << 8U; + ++txData; + tx_limit--; + } + } + else + { + wordToSend = dummyData; + } + + base->PUSHR = lastCommand | wordToSend; + + DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + remainingSendByteCount = 0; + + while (remainingReceiveByteCount > 0) + { + if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + { + if (remainingReceiveByteCount == 2) wait_cycles(100); // workaround for last sym issue on slave + wordReceived = DSPI_ReadData(base); + + if (remainingReceiveByteCount != 1) + { + if (rxData != NULL && rx_limit) + { + *(rxData) = wordReceived; + ++rxData; + *(rxData) = wordReceived >> 8; + ++rxData; + rx_limit--; + } + remainingReceiveByteCount -= 2; + } + else + { + if (rxData != NULL && rx_limit) + { + *(rxData) = wordReceived; + ++rxData; + rx_limit--; + } + remainingReceiveByteCount--; + } + DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + } + } + } + else + { + /*Wait until Tx Fifo is not full*/ + while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + { + DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + } + + if (txData != NULL && tx_limit) + { + wordToSend = *(txData); + ++txData; + wordToSend |= (unsigned)(*(txData)) << 8U; + ++txData; + tx_limit--; + } + else + { + wordToSend = dummyData; + } + base->PUSHR = command | wordToSend; + remainingSendByteCount -= 2; + + DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + + while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) + { + if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + { + wordReceived = DSPI_ReadData(base); + + if (rxData != NULL && rx_limit) + { + *rxData = wordReceived; + ++rxData; + *rxData = wordReceived >> 8; + ++rxData; + rx_limit--; + } + remainingReceiveByteCount -= 2; + + DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + } + } + } + } + } + + return kStatus_Success; +} + +void spi_get_capabilities(SPIName name, PinName ssel, spi_capabilities_t *cap) +{ + cap->word_length = 0x00008080; + cap->support_slave_mode = true; + cap->half_duplex = true; + + cap->minimum_frequency = 200000; + cap->maximum_frequency = 4000000; +} + +SPIName spi_get_module(PinName mosi, PinName miso, PinName sclk) { + int32_t spi_mosi = pinmap_find_peripheral(mosi, PinMap_SPI_SOUT); + int32_t spi_miso = pinmap_find_peripheral(miso, PinMap_SPI_SIN); + if ((spi_mosi == NC) && (spi_miso == NC)) { + // we're probably in slave mode. + spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_SIN); + spi_miso = pinmap_peripheral(miso, PinMap_SPI_SOUT); + } + int32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK); + int32_t spi_data = pinmap_merge(spi_mosi, spi_miso); + return pinmap_merge(spi_data, spi_sclk); +} + +void spi_init(spi_t *obj, bool is_slave, PinName mosi, PinName miso, PinName sclk, PinName ssel) { // determine the SPI to use - uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI); - uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO); - uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK); - uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL); - uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso); - uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel); - - obj->instance = pinmap_merge(spi_data, spi_cntl); + int32_t spi_module = (uint32_t)spi_get_module(mosi, miso, sclk); + int32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL); + MBED_ASSERT(spi_module != NC); + + obj->instance = pinmap_merge(spi_module, spi_ssel); MBED_ASSERT((int)obj->instance != NC); // pin out the spi pins - pinmap_pinout(mosi, PinMap_SPI_MOSI); - pinmap_pinout(miso, PinMap_SPI_MISO); + if (!is_slave) { + pinmap_pinout(mosi, PinMap_SPI_SOUT); + } else { + pinmap_pinout(mosi, PinMap_SPI_SIN); + } + if (!is_slave) { + pinmap_pinout(miso, PinMap_SPI_SIN); + } else { + pinmap_pinout(miso, PinMap_SPI_SOUT); + } pinmap_pinout(sclk, PinMap_SPI_SCLK); if (ssel != NC) { pinmap_pinout(ssel, PinMap_SPI_SSEL); } + obj->is_slave = is_slave; + obj->initialised = false; } void spi_free(spi_t *obj) { - DSPI_Deinit(spi_address[obj->instance]); + if (obj->initialised) { + DSPI_Deinit(spi_address[obj->instance]); + obj->initialised = false; + } } -void spi_format(spi_t *obj, int bits, int mode, int slave) +void spi_format(spi_t *obj, uint8_t bits, spi_mode_t mode, spi_bit_ordering_t bit_ordering) { dspi_master_config_t master_config; dspi_slave_config_t slave_config; + dspi_clock_polarity_t cpol; + dspi_clock_phase_t cpha; - if (slave) { + if ((mode == SPI_MODE_IDLE_HIGH_SAMPLE_FIRST_EDGE) || + (mode == SPI_MODE_IDLE_HIGH_SAMPLE_SECOND_EDGE)) { + cpol = kDSPI_ClockPolarityActiveLow; + } else { + cpol = kDSPI_ClockPolarityActiveHigh; + } + if ((mode == SPI_MODE_IDLE_HIGH_SAMPLE_FIRST_EDGE) || + (mode == SPI_MODE_IDLE_LOW_SAMPLE_FIRST_EDGE)) { + cpha = kDSPI_ClockPhaseFirstEdge; + } else { + cpha = kDSPI_ClockPhaseSecondEdge; + } + + /* Bits: values between 4 and 16 are valid */ + MBED_ASSERT(bits >= 4 && bits <= 16); + obj->bits = bits; + obj->order = bit_ordering; + + if (obj->is_slave) { /* Slave config */ DSPI_SlaveGetDefaultConfig(&slave_config); slave_config.whichCtar = kDSPI_Ctar0; - slave_config.ctarConfig.bitsPerFrame = (uint32_t)bits;; - slave_config.ctarConfig.cpol = (mode & 0x2) ? kDSPI_ClockPolarityActiveLow : kDSPI_ClockPolarityActiveHigh; - slave_config.ctarConfig.cpha = (mode & 0x1) ? kDSPI_ClockPhaseSecondEdge : kDSPI_ClockPhaseFirstEdge; + slave_config.ctarConfig.bitsPerFrame = (uint32_t)bits; + slave_config.ctarConfig.cpol = cpol; + slave_config.ctarConfig.cpha = cpha; DSPI_SlaveInit(spi_address[obj->instance], &slave_config); } else { /* Master config */ DSPI_MasterGetDefaultConfig(&master_config); - master_config.ctarConfig.bitsPerFrame = (uint32_t)bits;; - master_config.ctarConfig.cpol = (mode & 0x2) ? kDSPI_ClockPolarityActiveLow : kDSPI_ClockPolarityActiveHigh; - master_config.ctarConfig.cpha = (mode & 0x1) ? kDSPI_ClockPhaseSecondEdge : kDSPI_ClockPhaseFirstEdge; - master_config.ctarConfig.direction = kDSPI_MsbFirst; + master_config.ctarConfig.bitsPerFrame = (uint32_t)bits; + master_config.ctarConfig.cpol = cpol; + master_config.ctarConfig.cpha = cpha; + master_config.ctarConfig.direction = (bit_ordering == SPI_BIT_ORDERING_MSB_FIRST)? kDSPI_MsbFirst : kDSPI_LsbFirst; master_config.ctarConfig.pcsToSckDelayInNanoSec = 0; DSPI_MasterInit(spi_address[obj->instance], &master_config, CLOCK_GetFreq(spi_clocks[obj->instance])); } + + obj->initialised = true; } -void spi_frequency(spi_t *obj, int hz) +uint32_t spi_frequency(spi_t *obj, uint32_t hz) { uint32_t busClock = CLOCK_GetFreq(spi_clocks[obj->instance]); - DSPI_MasterSetBaudRate(spi_address[obj->instance], kDSPI_Ctar0, (uint32_t)hz, busClock); + uint32_t actual_br = DSPI_MasterSetBaudRate(spi_address[obj->instance], kDSPI_Ctar0, (uint32_t)hz, busClock); //Half clock period delay after SPI transfer - DSPI_MasterSetDelayTimes(spi_address[obj->instance], kDSPI_Ctar0, kDSPI_LastSckToPcs, busClock, 500000000 / hz); -} - -static inline int spi_readable(spi_t * obj) -{ - return (DSPI_GetStatusFlags(spi_address[obj->instance]) & kDSPI_RxFifoDrainRequestFlag); + DSPI_MasterSetDelayTimes(spi_address[obj->instance], kDSPI_Ctar0, kDSPI_LastSckToPcs, busClock, 2 * (1000000000 / hz)); + DSPI_MasterSetDelayTimes(spi_address[obj->instance], kDSPI_Ctar0, kDSPI_PcsToSck, busClock, 2 * (1000000000 / hz)); + DSPI_MasterSetDelayTimes(spi_address[obj->instance], kDSPI_Ctar0, kDSPI_BetweenTransfer, busClock, 0); + return actual_br; } -int spi_master_write(spi_t *obj, int value) +static int spi_write(spi_t *obj, uint32_t value) { - dspi_command_data_config_t command; uint32_t rx_data; - DSPI_GetDefaultDataCommandConfig(&command); - command.isEndOfQueue = true; - - DSPI_MasterWriteDataBlocking(spi_address[obj->instance], &command, (uint16_t)value); + if (obj->is_slave) { + DSPI_SlaveWriteDataBlocking(spi_address[obj->instance], value); + } else { + dspi_command_data_config_t command; + DSPI_GetDefaultDataCommandConfig(&command); + command.isEndOfQueue = true; - DSPI_ClearStatusFlags(spi_address[obj->instance], kDSPI_TxFifoFillRequestFlag); + DSPI_MasterWriteDataBlocking(spi_address[obj->instance], &command, (uint16_t)value); + // trigger the send ? + DSPI_ClearStatusFlags(spi_address[obj->instance], kDSPI_TxFifoFillRequestFlag); + } // wait rx buffer full - while (!spi_readable(obj)); + while (!(DSPI_GetStatusFlags(spi_address[obj->instance]) & kDSPI_RxFifoDrainRequestFlag)); rx_data = DSPI_ReadData(spi_address[obj->instance]); DSPI_ClearStatusFlags(spi_address[obj->instance], kDSPI_RxFifoDrainRequestFlag | kDSPI_EndOfQueueFlag); return rx_data & 0xffff; } -int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, - char *rx_buffer, int rx_length, char write_fill) { - int total = (tx_length > rx_length) ? tx_length : rx_length; +static void spi_irq_handler(spi_t *obj, status_t status) { + if (obj->handler != NULL) { + spi_async_handler_f handler = obj->handler; + void *ctx = obj->ctx; + obj->handler = NULL; + obj->ctx = NULL; - // Default write is done in each and every call, in future can create HAL API instead - DSPI_SetDummyData(spi_address[obj->instance], write_fill); + spi_async_event_t event = { + .transfered = obj->transfer_len, + .error = false + }; - DSPI_MasterTransferBlocking(spi_address[obj->instance], &(dspi_transfer_t){ - .txData = (uint8_t *)tx_buffer, - .rxData = (uint8_t *)rx_buffer, - .dataSize = total, - .configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcs0 | kDSPI_MasterPcsContinuous, - }); + handler(obj, ctx, &event); + } +} +static void spi_master_irq_handler(SPI_Type *base, dspi_master_handle_t *handle, status_t status, void *userData) { + spi_irq_handler(userData, status); +} +static void spi_slave_irq_callback(SPI_Type *base, dspi_slave_handle_t *handle, status_t status, void *userData) { + spi_irq_handler(userData, status); +} - DSPI_ClearStatusFlags(spi_address[obj->instance], kDSPI_RxFifoDrainRequestFlag | kDSPI_EndOfQueueFlag); +static void spi_sync_transfer_handler(spi_t *obj, void *ctx, spi_async_event_t *event) { + obj->transfered = event->transfered; +} - return total; +static uint32_t spi_symbol_size(spi_t *obj) { + if (obj->bits > 16) { return 4; } + else if (obj->bits > 8) { return 2; } + return 1; } -int spi_slave_receive(spi_t *obj) -{ - return spi_readable(obj); +static uint32_t spi_get_symbol(spi_t *obj, const void *from, uint32_t i) { + uint32_t val = 0; + switch (spi_symbol_size(obj)) { + case 1: + val = ((uint8_t *)from)[i]; + break; + case 2: + val = ((uint16_t *)from)[i]; + break; + case 4: + val = ((uint32_t *)from)[i]; + break; + default: + // TODO: TRAP ? + break; + } + return val; } -int spi_slave_read(spi_t *obj) -{ - uint32_t rx_data; +static void spi_set_symbol(spi_t *obj, void *to, uint32_t i, uint32_t val) { + switch (spi_symbol_size(obj)) { + case 1: + ((uint8_t *)to)[i] = val; + break; + case 2: + ((uint16_t *)to)[i] = val; + break; + case 4: + ((uint32_t *)to)[i] = val; + break; + default: + // TODO: TRAP ? + break; + } +} - while (!spi_readable(obj)); - rx_data = DSPI_ReadData(spi_address[obj->instance]); - DSPI_ClearStatusFlags(spi_address[obj->instance], kDSPI_RxFifoDrainRequestFlag); - return rx_data & 0xffff; +uint32_t spi_transfer(spi_t *obj, const void *tx_buffer, uint32_t tx_length, + void *rx_buffer, uint32_t rx_length, const void *fill) { + uint32_t total = 0; + if ((tx_length == 0) && (rx_length == 0)) { return 0; } + else if ((tx_length <= 1) && (rx_length <= 1)) { + uint32_t val_o = 0; + if (tx_length != 0) { + val_o = spi_get_symbol(obj, tx_buffer, 0); + } else { + val_o = spi_get_symbol(obj, fill, 0); + } + uint32_t val_i = spi_write(obj, val_o); + + if (rx_length != 0) { + spi_set_symbol(obj, rx_buffer, 0, val_i); + } + total = 1; + } else { + SPI_Type *spi = spi_address[obj->instance]; + + total = (tx_length > rx_length) ? tx_length : rx_length; + + DSPI_TransferBlockingLimit(spi, &(dspi_transfer_t){ + .txData = (uint8_t *)tx_buffer, + .rxData = (uint8_t *)rx_buffer, + .dataSize = total * spi_symbol_size(obj), + .configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcs0 | kDSPI_MasterPcsContinuous, + }, tx_length, rx_length, *(uint32_t *)fill); + + DSPI_ClearStatusFlags(spi, kDSPI_RxFifoDrainRequestFlag | kDSPI_EndOfQueueFlag); + } + + return total; } -void spi_slave_write(spi_t *obj, int value) +bool spi_transfer_async(spi_t *obj, const void *tx, uint32_t tx_len, void *rx, uint32_t rx_len, + const void *fill, spi_async_handler_f handler, void *ctx, DMAUsage hint) { - DSPI_SlaveWriteDataBlocking(spi_address[obj->instance], (uint32_t)value); + SPI_Type *spi = spi_address[obj->instance]; + + obj->handler = handler; + obj->ctx = ctx; + + DSPI_SetDummyData(spi, *(uint32_t *)fill); + uint32_t len = (rx_len>tx_len)?rx_len:tx_len; + obj->transfer_len = len; + + if (!obj->is_slave) { + dspi_master_handle_t *handle = &obj->u.master.handle; + DSPI_MasterTransferCreateHandle(spi, handle, spi_master_irq_handler, obj); + if (DSPI_MasterTransferNonBlocking(spi, handle, &(dspi_transfer_t){ + .txData = (uint8_t *)tx, + .rxData = (uint8_t *)rx, + .dataSize = len * spi_symbol_size(obj), + .configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcs0 | kDSPI_MasterPcsContinuous, + }) != kStatus_Success) { + return false; + } + DSPI_ClearStatusFlags(spi, kDSPI_RxFifoDrainRequestFlag | kDSPI_EndOfQueueFlag); + } else { + dspi_slave_handle_t *handle = &obj->u.slave.handle; + DSPI_SlaveTransferCreateHandle(spi, handle, spi_slave_irq_callback, obj); + if (DSPI_SlaveTransferNonBlocking(spi, handle, &(dspi_transfer_t){ + .txData = (uint8_t *)tx, + .rxData = (uint8_t *)rx, + .dataSize = len * spi_symbol_size(obj), + .configFlags = kDSPI_SlaveCtar0, + }) != kStatus_Success) { + return false; + } + } + return true; +} + +void spi_transfer_async_abort(spi_t *obj) { + SPI_Type *spi = spi_address[obj->instance]; + + if (obj->is_slave) { + DSPI_SlaveTransferAbort(spi, &obj->u.slave.handle); + } else { + DSPI_MasterTransferAbort(spi, &obj->u.master.handle); + } } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/PeripheralPins.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/PeripheralPins.h index ad78a7dc53e..bd28ba98153 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/PeripheralPins.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/PeripheralPins.h @@ -40,8 +40,8 @@ extern const PinMap PinMap_UART_CTS[]; extern const PinMap PinMap_UART_RTS[]; /************SPI***************/ extern const PinMap PinMap_SPI_SCLK[]; -extern const PinMap PinMap_SPI_MOSI[]; -extern const PinMap PinMap_SPI_MISO[]; +extern const PinMap PinMap_SPI_SOUT[]; +extern const PinMap PinMap_SPI_SIN[]; extern const PinMap PinMap_SPI_SSEL[]; /************PWM***************/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/objects.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/objects.h index 405f2e17785..194deeefeb8 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/objects.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/objects.h @@ -20,8 +20,9 @@ #include "PortNames.h" #include "PeripheralNames.h" #include "PinNames.h" -#if DEVICE_SPI_ASYNCH +#if DEVICE_SPI #include "fsl_dspi_edma.h" +#include "spi_api.h" #endif #if DEVICE_SERIAL_ASYNCH #include "fsl_uart_edma.h" @@ -70,18 +71,33 @@ struct i2c_s { uint8_t next_repeated_start; }; +#if DEVICE_SPI struct spi_s { uint32_t instance; uint8_t bits; + bool is_slave; + spi_bit_ordering_t order; + bool initialised; #if DEVICE_SPI_ASYNCH + spi_async_handler_f handler; + void *ctx; + uint32_t transfer_len; + volatile uint32_t transfered; + status_t status; + dspi_master_handle_t spi_master_handle; - dspi_master_edma_handle_t spi_dma_master_handle; - dma_options_t spiDmaMasterRx; - dma_options_t spiDmaMasterTx; - dma_options_t spiDmaMasterIntermediary; + union mode_u { + struct master_s { + dspi_master_handle_t handle; + } master; + struct slave_s { + dspi_slave_handle_t handle; + } slave; + } u; #endif }; +#endif struct dac_s { DACName dac; diff --git a/targets/TARGET_Maxim/TARGET_MAX32600/spi_api.c b/targets/TARGET_Maxim/TARGET_MAX32600/spi_api.c index edf5ab2f137..9d2b464bbb0 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32600/spi_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32600/spi_api.c @@ -31,6 +31,8 @@ ******************************************************************************* */ +#if DEVICE_SPI + #include #include "mbed_assert.h" #include "cmsis.h" @@ -199,3 +201,5 @@ int spi_busy(spi_t *obj) { return !(obj->spi->intfl & MXC_F_SPI_INTFL_TX_READY); } + +#endif diff --git a/targets/TARGET_Maxim/TARGET_MAX32610/spi_api.c b/targets/TARGET_Maxim/TARGET_MAX32610/spi_api.c index edf5ab2f137..9d2b464bbb0 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32610/spi_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32610/spi_api.c @@ -31,6 +31,8 @@ ******************************************************************************* */ +#if DEVICE_SPI + #include #include "mbed_assert.h" #include "cmsis.h" @@ -199,3 +201,5 @@ int spi_busy(spi_t *obj) { return !(obj->spi->intfl & MXC_F_SPI_INTFL_TX_READY); } + +#endif diff --git a/targets/TARGET_Maxim/TARGET_MAX32620/spi_api.c b/targets/TARGET_Maxim/TARGET_MAX32620/spi_api.c index d2a194366dd..a33fd70be21 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32620/spi_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32620/spi_api.c @@ -31,6 +31,8 @@ ******************************************************************************* */ +#if DEVICE_SPI + #include #include "mbed_assert.h" #include "cmsis.h" @@ -573,3 +575,5 @@ void SPI1_IRQHandler(void) { SPI_IRQHandler(1); } void SPI2_IRQHandler(void) { SPI_IRQHandler(2); } #endif + +#endif diff --git a/targets/TARGET_Maxim/TARGET_MAX32620C/spi_api.c b/targets/TARGET_Maxim/TARGET_MAX32620C/spi_api.c index 4410bdd3cd4..13772447a90 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32620C/spi_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32620C/spi_api.c @@ -31,6 +31,8 @@ ******************************************************************************* */ +#if DEVICE_SPI + #include "mbed_assert.h" #include "mbed_critical.h" #include "spi_api.h" // mbed HAL @@ -233,3 +235,5 @@ uint8_t spi_get_module(spi_t *obj) { return obj->index; } + +#endif diff --git a/targets/TARGET_Maxim/TARGET_MAX32625/spi_api.c b/targets/TARGET_Maxim/TARGET_MAX32625/spi_api.c index 4410bdd3cd4..13772447a90 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32625/spi_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32625/spi_api.c @@ -31,6 +31,8 @@ ******************************************************************************* */ +#if DEVICE_SPI + #include "mbed_assert.h" #include "mbed_critical.h" #include "spi_api.h" // mbed HAL @@ -233,3 +235,5 @@ uint8_t spi_get_module(spi_t *obj) { return obj->index; } + +#endif diff --git a/targets/TARGET_Maxim/TARGET_MAX32630/spi_api.c b/targets/TARGET_Maxim/TARGET_MAX32630/spi_api.c index 676a7e08256..fdb75896380 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32630/spi_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32630/spi_api.c @@ -31,6 +31,8 @@ ******************************************************************************* */ +#if DEVICE_SPI + #include "mbed_assert.h" #include "mbed_critical.h" #include "spi_api.h" // mbed HAL @@ -233,3 +235,5 @@ uint8_t spi_get_module(spi_t *obj) { return obj->index; } + +#endif diff --git a/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/spi_api.c b/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/spi_api.c index b1f354e77ef..cbfd9455c4a 100755 --- a/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/spi_api.c +++ b/targets/TARGET_NORDIC/TARGET_MCU_NRF51822/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + //#include #include "mbed_assert.h" #include "spi_api.h" @@ -299,3 +302,5 @@ void spi_slave_write(spi_t *obj, int value) obj->spis->EVENTS_ACQUIRED = 0; obj->spis->EVENTS_END = 0; } + +#endif diff --git a/targets/TARGET_NXP/TARGET_LPC11UXX/spi_api.c b/targets/TARGET_NXP/TARGET_LPC11UXX/spi_api.c index 19d40f2ff36..a1e04ebd8f7 100644 --- a/targets/TARGET_NXP/TARGET_LPC11UXX/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC11UXX/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include #include "spi_api.h" @@ -187,3 +190,5 @@ void spi_slave_write(spi_t *obj, int value) { int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_NXP/TARGET_LPC11XX_11CXX/spi_api.c b/targets/TARGET_NXP/TARGET_LPC11XX_11CXX/spi_api.c index f7ac3488b02..db3fc198799 100644 --- a/targets/TARGET_NXP/TARGET_LPC11XX_11CXX/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC11XX_11CXX/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include #include "spi_api.h" @@ -223,3 +226,5 @@ void spi_slave_write(spi_t *obj, int value) { int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_NXP/TARGET_LPC13XX/spi_api.c b/targets/TARGET_NXP/TARGET_LPC13XX/spi_api.c index f6243fde4a4..607697b994a 100644 --- a/targets/TARGET_NXP/TARGET_LPC13XX/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC13XX/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include #include "spi_api.h" @@ -215,3 +218,5 @@ void spi_slave_write(spi_t *obj, int value) { int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_NXP/TARGET_LPC15XX/spi_api.c b/targets/TARGET_NXP/TARGET_LPC15XX/spi_api.c index 9d7d8f5f001..c64e7945b3c 100644 --- a/targets/TARGET_NXP/TARGET_LPC15XX/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC15XX/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include @@ -278,3 +281,5 @@ void spi_slave_write(spi_t *obj, int value) while (spi_writeable(obj) == 0) ; obj->spi->TXDAT = value; } + +#endif diff --git a/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c b/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c index cc30a264e8a..c848399381f 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include @@ -221,3 +224,5 @@ void spi_slave_write(spi_t *obj, int value) { int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088/spi_api.c b/targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088/spi_api.c index 9fdf2331db7..558612008f2 100644 --- a/targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include #include "spi_api.h" @@ -229,3 +232,5 @@ void spi_slave_write(spi_t *obj, int value) { int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088_DM/spi_api.c b/targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088_DM/spi_api.c index b6a158b4812..59e0b5afab8 100644 --- a/targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088_DM/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088_DM/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include #include "spi_api.h" @@ -208,3 +211,5 @@ void spi_slave_write(spi_t *obj, int value) { int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_NXP/TARGET_LPC43XX/spi_api.c b/targets/TARGET_NXP/TARGET_LPC43XX/spi_api.c index ac30524aef4..d785d2c4d7f 100644 --- a/targets/TARGET_NXP/TARGET_LPC43XX/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC43XX/spi_api.c @@ -15,6 +15,9 @@ * * Ported to NXP LPC43XX by Micromint USA */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include @@ -227,3 +230,5 @@ void spi_slave_write(spi_t *obj, int value) { int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_NXP/TARGET_LPC81X/spi_api.c b/targets/TARGET_NXP/TARGET_LPC81X/spi_api.c index 88ba0a725fe..862106d0b98 100644 --- a/targets/TARGET_NXP/TARGET_LPC81X/spi_api.c +++ b/targets/TARGET_NXP/TARGET_LPC81X/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include @@ -209,3 +212,5 @@ void spi_slave_write(spi_t *obj, int value) { int spi_busy(spi_t *obj) { return ssp_busy(obj); } + +#endif diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/spi_api.c b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/spi_api.c index 256d69c6a43..5f35c526117 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/spi_api.c +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "mbed_assert.h" #include @@ -536,3 +539,4 @@ void spi_abort_asynch(spi_t *obj) } #endif +#endif diff --git a/targets/TARGET_Realtek/TARGET_AMEBA/TARGET_MCU_RTL8195A/spi_api.c b/targets/TARGET_Realtek/TARGET_AMEBA/TARGET_MCU_RTL8195A/spi_api.c index e4596a14604..496935b0494 100644 --- a/targets/TARGET_Realtek/TARGET_AMEBA/TARGET_MCU_RTL8195A/spi_api.c +++ b/targets/TARGET_Realtek/TARGET_AMEBA/TARGET_MCU_RTL8195A/spi_api.c @@ -14,6 +14,8 @@ * limitations under the License. */ +#if DEVICE_SPI + #include "objects.h" #include "spi_api.h" #include "spi_ex_api.h" @@ -373,3 +375,4 @@ void spi_rx_done_callback(VOID *obj) } } +#endif diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F429xI/TARGET_NUCLEO_F429ZI/PeripheralNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F429xI/TARGET_NUCLEO_F429ZI/PeripheralNames.h index d2c2320ba5b..773fdfa77fe 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F429xI/TARGET_NUCLEO_F429ZI/PeripheralNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F429xI/TARGET_NUCLEO_F429ZI/PeripheralNames.h @@ -57,6 +57,7 @@ typedef enum { UART_8 = (int)UART8_BASE } UARTName; +#define SPI_COUNT 6 typedef enum { SPI_1 = (int)SPI1_BASE, SPI_2 = (int)SPI2_BASE, diff --git a/targets/TARGET_STM/TARGET_STM32F4/common_objects.h b/targets/TARGET_STM/TARGET_STM32F4/common_objects.h index 3f39a9ce53b..1cbda6689c9 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/common_objects.h +++ b/targets/TARGET_STM/TARGET_STM32F4/common_objects.h @@ -34,6 +34,8 @@ #include "PortNames.h" #include "PeripheralNames.h" #include "PinNames.h" +#include "hal/buffer.h" +#include "hal/spi_api.h" #ifdef __cplusplus extern "C" { @@ -77,8 +79,12 @@ struct spi_s { PinName pin_sclk; PinName pin_ssel; #ifdef DEVICE_SPI_ASYNCH - uint32_t event; uint8_t transfer_type; + spi_async_handler_f handler; + void *ctx; + uint16_t fill_symbol; + struct buffer_s tx_buff; + struct buffer_s rx_buff; #endif }; diff --git a/targets/TARGET_STM/TARGET_STM32F4/spi_api.c b/targets/TARGET_STM/TARGET_STM32F4/spi_api.c index 4b62c424ffd..ee40f8bdd7e 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/spi_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/spi_api.c @@ -29,6 +29,7 @@ */ #include "mbed_assert.h" #include "mbed_error.h" +#include "common_objects.h" #include "spi_api.h" #if DEVICE_SPI @@ -39,11 +40,7 @@ #include "pinmap.h" #include "PeripheralPins.h" -#if DEVICE_SPI_ASYNCH -#define SPI_S(obj) (( struct spi_s *)(&(obj->spi))) -#else #define SPI_S(obj) (( struct spi_s *)(obj)) -#endif /* * Only the frequency is managed in the family specific part diff --git a/targets/TARGET_STM/stm_spi_api.c b/targets/TARGET_STM/stm_spi_api.c index 64cd9bdfbb1..3f25969fe65 100644 --- a/targets/TARGET_STM/stm_spi_api.c +++ b/targets/TARGET_STM/stm_spi_api.c @@ -40,18 +40,10 @@ #include "pinmap.h" #include "PeripheralPins.h" #include "spi_device.h" +#include "device.h" -#if DEVICE_SPI_ASYNCH -#define SPI_INST(obj) ((SPI_TypeDef *)(obj->spi.spi)) -#else #define SPI_INST(obj) ((SPI_TypeDef *)(obj->spi)) -#endif - -#if DEVICE_SPI_ASYNCH -#define SPI_S(obj) (( struct spi_s *)(&(obj->spi))) -#else #define SPI_S(obj) (( struct spi_s *)(obj)) -#endif #ifndef DEBUG_STDIO # define DEBUG_STDIO 0 @@ -71,6 +63,60 @@ extern HAL_StatusTypeDef HAL_SPIEx_FlushRxFifo(SPI_HandleTypeDef *hspi); #endif +static void spi_irq_handler(spi_t *); + +#if defined SPI1_BASE +spi_t *spi1 = NULL; +void spi1_irq_handler(void) { + spi_irq_handler(spi1); +} +#endif + +#if defined SPI2_BASE +spi_t *spi2 = NULL; +void spi2_irq_handler(void) { + spi_irq_handler(spi2); +} +#endif + +#if defined SPI3_BASE +spi_t *spi3 = NULL; +void spi3_irq_handler(void) { + spi_irq_handler(spi3); +} +#endif + +#if defined SPI4_BASE +spi_t *spi4 = NULL; +void spi4_irq_handler(void) { + spi_irq_handler(spi4); +} +#endif + +#if defined SPI5_BASE +spi_t *spi5 = NULL; +void spi5_irq_handler(void) { + spi_irq_handler(spi5); +} +#endif + +#if defined SPI6_BASE +spi_t *spi6 = NULL; +void spi6_irq_handler(void) { + spi_irq_handler(spi6); +} +#endif + +void spi_get_capabilities(SPIName name, PinName ssel, spi_capabilities_t *cap) +{ + cap->word_length = 0x00008080; + cap->support_slave_mode = true; + cap->half_duplex = true; + + cap->minimum_frequency = 200000; + cap->maximum_frequency = 4000000; +} + void init_spi(spi_t *obj) { struct spi_s *spiobj = SPI_S(obj); @@ -93,28 +139,41 @@ void init_spi(spi_t *obj) } } -void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) +SPIName spi_get_module(PinName mosi, PinName miso, PinName sclk) { + SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); + SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); + SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); + + SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); + + return (SPIName)pinmap_merge(spi_data, spi_sclk); +} + +void spi_init(spi_t *obj, bool is_slave, PinName mosi, PinName miso, PinName sclk, PinName ssel) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); // Determine the SPI to use - SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); - SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); - SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); + SPIName spi_module = spi_get_module(mosi, miso, sclk); SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); + if (is_slave && (ssel == NC)) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_PINMAP_INVALID), "missing slave select pin"); + } - SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); - SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); - - spiobj->spi = (SPIName)pinmap_merge(spi_data, spi_cntl); + spiobj->spi = (SPIName)pinmap_merge(spi_module, spi_ssel); MBED_ASSERT(spiobj->spi != (SPIName)NC); + void (*irq_vector)(void) = NULL; #if defined SPI1_BASE // Enable SPI clock if (spiobj->spi == SPI_1) { __HAL_RCC_SPI1_CLK_ENABLE(); spiobj->spiIRQ = SPI1_IRQn; + + MBED_ASSERT((spi1 == NULL) || (spi1 == obj)); + spi1 = obj; + irq_vector = spi1_irq_handler; } #endif @@ -122,6 +181,10 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel if (spiobj->spi == SPI_2) { __HAL_RCC_SPI2_CLK_ENABLE(); spiobj->spiIRQ = SPI2_IRQn; + + MBED_ASSERT((spi2 == NULL) || (spi2 == obj)); + spi2 = obj; + irq_vector = spi2_irq_handler; } #endif @@ -129,6 +192,10 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel if (spiobj->spi == SPI_3) { __HAL_RCC_SPI3_CLK_ENABLE(); spiobj->spiIRQ = SPI3_IRQn; + + MBED_ASSERT((spi3 == NULL) || (spi3 == obj)); + spi3 = obj; + irq_vector = spi3_irq_handler; } #endif @@ -136,6 +203,10 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel if (spiobj->spi == SPI_4) { __HAL_RCC_SPI4_CLK_ENABLE(); spiobj->spiIRQ = SPI4_IRQn; + + MBED_ASSERT((spi4 == NULL) || (spi4 == obj)); + spi4 = obj; + irq_vector = spi4_irq_handler; } #endif @@ -143,6 +214,10 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel if (spiobj->spi == SPI_5) { __HAL_RCC_SPI5_CLK_ENABLE(); spiobj->spiIRQ = SPI5_IRQn; + + MBED_ASSERT((spi5 == NULL) || (spi5 == obj)); + spi5 = obj; + irq_vector = spi5_irq_handler; } #endif @@ -150,6 +225,10 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel if (spiobj->spi == SPI_6) { __HAL_RCC_SPI6_CLK_ENABLE(); spiobj->spiIRQ = SPI6_IRQn; + + MBED_ASSERT((spi6 == NULL) || (spi6 == obj)); + spi6 = obj; + irq_vector = spi6_irq_handler; } #endif @@ -163,20 +242,32 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel spiobj->pin_ssel = ssel; if (ssel != NC) { pinmap_pinout(ssel, PinMap_SPI_SSEL); - handle->Init.NSS = SPI_NSS_HARD_OUTPUT; + if (is_slave) { + handle->Init.NSS = SPI_NSS_HARD_INPUT; + } else { + handle->Init.NSS = SPI_NSS_HARD_OUTPUT; + } } else { handle->Init.NSS = SPI_NSS_SOFT; } /* Fill default value */ handle->Instance = SPI_INST(obj); - handle->Init.Mode = SPI_MODE_MASTER; + handle->Init.Mode = is_slave ? SPI_MODE_SLAVE : SPI_MODE_MASTER; handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; - if (miso != NC) { - handle->Init.Direction = SPI_DIRECTION_2LINES; + if (is_slave) { + if (mosi != NC) { + handle->Init.Direction = SPI_DIRECTION_2LINES; + } else { + handle->Init.Direction = SPI_DIRECTION_1LINE; + } } else { - handle->Init.Direction = SPI_DIRECTION_1LINE; + if (miso != NC) { + handle->Init.Direction = SPI_DIRECTION_2LINES; + } else { + handle->Init.Direction = SPI_DIRECTION_1LINE; + } } handle->Init.CLKPhase = SPI_PHASE_1EDGE; @@ -187,6 +278,14 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel handle->Init.FirstBit = SPI_FIRSTBIT_MSB; handle->Init.TIMode = SPI_TIMODE_DISABLE; +#ifdef DEVICE_SPI_ASYNCH + IRQn_Type irq_n = spiobj->spiIRQ; + NVIC_DisableIRQ(irq_n); + NVIC_ClearPendingIRQ(irq_n); + NVIC_SetVector(irq_n, (uint32_t)irq_vector); + DEBUG_PRINTF("init_spi: vector=%d\n", irq_n); +#endif + init_spi(obj); } @@ -203,6 +302,8 @@ void spi_free(spi_t *obj) #if defined SPI1_BASE // Reset SPI and disable clock if (spiobj->spi == SPI_1) { + MBED_ASSERT(spi1 == obj); + spi1 = NULL; __HAL_RCC_SPI1_FORCE_RESET(); __HAL_RCC_SPI1_RELEASE_RESET(); __HAL_RCC_SPI1_CLK_DISABLE(); @@ -210,6 +311,8 @@ void spi_free(spi_t *obj) #endif #if defined SPI2_BASE if (spiobj->spi == SPI_2) { + MBED_ASSERT(spi2 == obj); + spi2 = NULL; __HAL_RCC_SPI2_FORCE_RESET(); __HAL_RCC_SPI2_RELEASE_RESET(); __HAL_RCC_SPI2_CLK_DISABLE(); @@ -218,6 +321,8 @@ void spi_free(spi_t *obj) #if defined SPI3_BASE if (spiobj->spi == SPI_3) { + MBED_ASSERT(spi3 == obj); + spi3 = NULL; __HAL_RCC_SPI3_FORCE_RESET(); __HAL_RCC_SPI3_RELEASE_RESET(); __HAL_RCC_SPI3_CLK_DISABLE(); @@ -226,6 +331,8 @@ void spi_free(spi_t *obj) #if defined SPI4_BASE if (spiobj->spi == SPI_4) { + MBED_ASSERT(spi4 == obj); + spi4 = NULL; __HAL_RCC_SPI4_FORCE_RESET(); __HAL_RCC_SPI4_RELEASE_RESET(); __HAL_RCC_SPI4_CLK_DISABLE(); @@ -234,6 +341,8 @@ void spi_free(spi_t *obj) #if defined SPI5_BASE if (spiobj->spi == SPI_5) { + MBED_ASSERT(spi5 == obj); + spi5 = NULL; __HAL_RCC_SPI5_FORCE_RESET(); __HAL_RCC_SPI5_RELEASE_RESET(); __HAL_RCC_SPI5_CLK_DISABLE(); @@ -242,6 +351,8 @@ void spi_free(spi_t *obj) #if defined SPI6_BASE if (spiobj->spi == SPI_6) { + MBED_ASSERT(spi6 == obj); + spi6 = NULL; __HAL_RCC_SPI6_FORCE_RESET(); __HAL_RCC_SPI6_RELEASE_RESET(); __HAL_RCC_SPI6_CLK_DISABLE(); @@ -249,23 +360,28 @@ void spi_free(spi_t *obj) #endif // Configure GPIOs - pin_function(spiobj->pin_miso, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); - pin_function(spiobj->pin_mosi, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + if (spiobj->pin_miso != NC) { + pin_function(spiobj->pin_miso, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + } + if (spiobj->pin_mosi != NC) { + pin_function(spiobj->pin_mosi, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); + } pin_function(spiobj->pin_sclk, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); if (handle->Init.NSS != SPI_NSS_SOFT) { pin_function(spiobj->pin_ssel, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); } } -void spi_format(spi_t *obj, int bits, int mode, int slave) +void spi_format(spi_t *obj, uint8_t bits, spi_mode_t mode, spi_bit_ordering_t bit_ordering) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); - DEBUG_PRINTF("spi_format, bits:%d, mode:%d, slave?:%d\r\n", bits, mode, slave); + DEBUG_PRINTF("spi_format, bits:%d, mode:%d\n", bits, mode); // Save new values handle->Init.DataSize = (bits == 16) ? SPI_DATASIZE_16BIT : SPI_DATASIZE_8BIT; + handle->Init.FirstBit = (bit_ordering == SPI_BIT_ORDERING_MSB_FIRST) ? SPI_FIRSTBIT_MSB : SPI_FIRSTBIT_LSB; switch (mode) { case 0: @@ -286,22 +402,6 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) break; } - if (handle->Init.NSS != SPI_NSS_SOFT) { - handle->Init.NSS = (slave) ? SPI_NSS_HARD_INPUT : SPI_NSS_HARD_OUTPUT; - } - - handle->Init.Mode = (slave) ? SPI_MODE_SLAVE : SPI_MODE_MASTER; - - if (slave && (handle->Init.Direction == SPI_DIRECTION_1LINE)) { - /* SPI slave implemtation in MBED does not support the 3 wires SPI. - * (e.g. when MISO is not connected). So we're forcing slave in - * 2LINES mode. As MISO is not connected, slave will only read - * from master, and cannot write to it. Inform user. - */ - debug("3 wires SPI slave not supported - slave will only read\r\n"); - handle->Init.Direction = SPI_DIRECTION_2LINES; - } - init_spi(obj); } @@ -321,10 +421,10 @@ static const uint16_t baudrate_prescaler_table[] = {SPI_BAUDRATEPRESCALER_2, SPI_BAUDRATEPRESCALER_256 }; -void spi_frequency(spi_t *obj, int hz) +uint32_t spi_frequency(spi_t *obj, uint32_t hz) { struct spi_s *spiobj = SPI_S(obj); - int spi_hz = 0; + uint32_t spi_hz = 0; uint8_t prescaler_rank = 0; uint8_t last_index = (sizeof(baudrate_prescaler_table) / sizeof(baudrate_prescaler_table[0])) - 1; SPI_HandleTypeDef *handle = &(spiobj->handle); @@ -343,54 +443,20 @@ void spi_frequency(spi_t *obj, int hz) /* In case maximum pre-scaler still gives too high freq, raise an error */ if (spi_hz > hz) { - DEBUG_PRINTF("WARNING: lowest SPI freq (%d) higher than requested (%d)\r\n", spi_hz, hz); + DEBUG_PRINTF("WARNING: lowest SPI freq (%lu) higher than requested (%lu)\n", spi_hz, hz); } - DEBUG_PRINTF("spi_frequency, request:%d, select:%d\r\n", hz, spi_hz); + DEBUG_PRINTF("spi_frequency, request:%lu, select:%lu\n", hz, spi_hz); init_spi(obj); -} - -static inline int ssp_readable(spi_t *obj) -{ - int status; - struct spi_s *spiobj = SPI_S(obj); - SPI_HandleTypeDef *handle = &(spiobj->handle); - - // Check if data is received - status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_RXNE) != RESET) ? 1 : 0); - return status; -} - -static inline int ssp_writeable(spi_t *obj) -{ - int status; - struct spi_s *spiobj = SPI_S(obj); - SPI_HandleTypeDef *handle = &(spiobj->handle); - - // Check if data is transmitted - status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_TXE) != RESET) ? 1 : 0); - return status; -} -static inline int ssp_busy(spi_t *obj) -{ - int status; - struct spi_s *spiobj = SPI_S(obj); - SPI_HandleTypeDef *handle = &(spiobj->handle); - status = ((__HAL_SPI_GET_FLAG(handle, SPI_FLAG_BSY) != RESET) ? 1 : 0); - return status; + return spi_hz; } -int spi_master_write(spi_t *obj, int value) -{ +static uint32_t spi_write(spi_t *obj, uint32_t value) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); - if (handle->Init.Direction == SPI_DIRECTION_1LINE) { - return HAL_SPI_Transmit(handle, (uint8_t *)&value, 1, TIMEOUT_1_BYTE); - } - #if defined(LL_SPI_RX_FIFO_TH_HALF) /* Configure the default data size */ if (handle->Init.DataSize == SPI_DATASIZE_16BIT) { @@ -418,40 +484,82 @@ int spi_master_write(spi_t *obj, int value) /* Then wait RXE flag before reading */ while (!LL_SPI_IsActiveFlag_RXNE(SPI_INST(obj))); + uint32_t out = 0; if (handle->Init.DataSize == SPI_DATASIZE_16BIT) { - return LL_SPI_ReceiveData16(SPI_INST(obj)); + out = LL_SPI_ReceiveData16(SPI_INST(obj)); } else { - return LL_SPI_ReceiveData8(SPI_INST(obj)); + out = LL_SPI_ReceiveData8(SPI_INST(obj)); } + return out; } -int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, - char *rx_buffer, int rx_length, char write_fill) +uint32_t spi_transfer(spi_t *obj, const void *tx_buffer, uint32_t tx_length, + void *rx_buffer, uint32_t rx_length, const void *write_fill) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); - int total = (tx_length > rx_length) ? tx_length : rx_length; - int i = 0; + uint32_t total = (tx_length > rx_length) ? tx_length : rx_length; + uint32_t i = 0; if (handle->Init.Direction == SPI_DIRECTION_2LINES) { for (i = 0; i < total; i++) { - char out = (i < tx_length) ? tx_buffer[i] : write_fill; - char in = spi_master_write(obj, out); - if (i < rx_length) { - rx_buffer[i] = in; + uint32_t out, in; + switch (handle->Init.DataSize) { + case SPI_DATASIZE_8BIT: + if (tx_buffer) { + out = (i < tx_length) ? ((uint8_t *)tx_buffer)[i] : *(uint8_t *)write_fill; + } else { + out = *(uint8_t *)write_fill; + } + in = spi_write(obj, out); + if (i < rx_length) { + ((uint8_t*)rx_buffer)[i] = (uint8_t)in; + } + break; + case SPI_DATASIZE_16BIT: + if (tx_buffer) { + out = (i < tx_length) ? ((uint16_t *)tx_buffer)[i] : *(uint16_t *)write_fill; + } else { + out = *(uint16_t *)write_fill; + } + in = spi_write(obj, out); + if (i < rx_length) { + ((uint16_t*)rx_buffer)[i] = (uint16_t)in; + } + break; + default: + break; } } } else { /* In case of 1 WIRE only, first handle TX, then Rx */ - if (tx_length != 0) { - if (HAL_OK != HAL_SPI_Transmit(handle, (uint8_t *)tx_buffer, tx_length, tx_length * TIMEOUT_1_BYTE)) { - /* report an error */ - total = 0; + + total = tx_length + rx_length; + + if (handle->Init.Mode == SPI_MODE_MASTER) { + if (tx_length != 0) { + if (HAL_OK != HAL_SPI_Transmit(handle, (uint8_t *)tx_buffer, tx_length, tx_length * TIMEOUT_1_BYTE)) { + /* report an error */ + total = 0; + } } - } - if (rx_length != 0) { - if (HAL_OK != HAL_SPI_Receive(handle, (uint8_t *)rx_buffer, rx_length, rx_length * TIMEOUT_1_BYTE)) { - /* report an error */ - total = 0; + if (rx_length != 0) { + if (HAL_OK != HAL_SPI_Receive(handle, (uint8_t *)rx_buffer, rx_length, rx_length * TIMEOUT_1_BYTE)) { + /* report an error */ + total = 0; + } + } + } else { + if (rx_length != 0) { + if (HAL_OK != HAL_SPI_Receive(handle, (uint8_t *)rx_buffer, rx_length, HAL_MAX_DELAY)) { + /* report an error */ + total = 0; + } + } + if (tx_length != 0) { + if (HAL_OK != HAL_SPI_Transmit(handle, (uint8_t *)tx_buffer, tx_length, HAL_MAX_DELAY)) { + /* report an error */ + total = 0; + } } } } @@ -459,44 +567,6 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, return total; } -int spi_slave_receive(spi_t *obj) -{ - return ((ssp_readable(obj) && !ssp_busy(obj)) ? 1 : 0); -}; - -int spi_slave_read(spi_t *obj) -{ - struct spi_s *spiobj = SPI_S(obj); - SPI_HandleTypeDef *handle = &(spiobj->handle); - while (!ssp_readable(obj)); - if (handle->Init.DataSize == SPI_DATASIZE_16BIT) { - return LL_SPI_ReceiveData16(SPI_INST(obj)); - } else { - return LL_SPI_ReceiveData8(SPI_INST(obj)); - } -} - -void spi_slave_write(spi_t *obj, int value) -{ - SPI_TypeDef *spi = SPI_INST(obj); - struct spi_s *spiobj = SPI_S(obj); - SPI_HandleTypeDef *handle = &(spiobj->handle); - while (!ssp_writeable(obj)); - if (handle->Init.DataSize == SPI_DATASIZE_8BIT) { - // Force 8-bit access to the data register - uint8_t *p_spi_dr = 0; - p_spi_dr = (uint8_t *) & (spi->DR); - *p_spi_dr = (uint8_t)value; - } else { // SPI_DATASIZE_16BIT - spi->DR = (uint16_t)value; - } -} - -int spi_busy(spi_t *obj) -{ - return ssp_busy(obj); -} - #ifdef DEVICE_SPI_ASYNCH typedef enum { SPI_TRANSFER_TYPE_NONE = 0, @@ -505,31 +575,31 @@ typedef enum { SPI_TRANSFER_TYPE_TXRX = 3, } transfer_type_t; - /// @returns the number of bytes transferred, or `0` if nothing transferred -static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer_type, const void *tx, void *rx, size_t length) +static void spi_start_asynch_transfer(spi_t *obj, transfer_type_t transfer_type, const void *tx, void *rx, size_t length, const void *fill_symbol) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); bool is16bit = (handle->Init.DataSize == SPI_DATASIZE_16BIT); + + if (is16bit) { + obj->fill_symbol = *(uint16_t *)fill_symbol; + } else { + obj->fill_symbol = *(uint8_t *)fill_symbol; + } + // the HAL expects number of transfers instead of number of bytes // so for 16 bit transfer width the count needs to be halved size_t words; - DEBUG_PRINTF("SPI inst=0x%8X Start: %u, %u\r\n", (int)handle->Instance, transfer_type, length); + DEBUG_PRINTF("SPI inst=0x%8X Start: %u, %u\n", (int)handle->Instance, transfer_type, length); - obj->spi.transfer_type = transfer_type; + obj->transfer_type = transfer_type; - if (is16bit) { - words = length / 2; - } else { - words = length; - } + words = length; // enable the interrupt IRQn_Type irq_n = spiobj->spiIRQ; - NVIC_DisableIRQ(irq_n); - NVIC_ClearPendingIRQ(irq_n); NVIC_SetPriority(irq_n, 1); NVIC_EnableIRQ(irq_n); @@ -549,9 +619,9 @@ static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer break; case SPI_TRANSFER_TYPE_RX: // the receive function also "transmits" the receive buffer so in order - // to guarantee that 0xff is on the line, we explicitly memset it here - memset(rx, SPI_FILL_WORD, length); - rc = HAL_SPI_Receive_IT(handle, (uint8_t *)rx, words); + // to guarantee that fill sym is on the line, we explicitly memset it here + memset(rx, *(uint8_t*)fill_symbol, length); // this only works for 8 bit symbols though + rc = HAL_SPI_TransmitReceive_IT(handle, (uint8_t *)rx, (uint8_t *)rx, words); break; default: length = 0; @@ -559,14 +629,63 @@ static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer if (rc) { DEBUG_PRINTF("SPI: RC=%u\n", rc); - length = 0; } +} + +static void spi_irq_handler(spi_t *obj) +{ + // call the CubeF4 handler, this will update the handle + HAL_SPI_IRQHandler(&obj->handle); + + if (obj->handle.State == HAL_SPI_STATE_READY) { + // When HAL SPI is back to READY state, check if there was an error + int error = obj->handle.ErrorCode; +#ifndef MAX + // quick & dirty max impl +#define MAX(a, b) ((a>b)?(a):(b)) +#endif + + obj->tx_buff.pos += obj->handle.TxXferSize; + obj->rx_buff.pos += obj->handle.RxXferSize; + bool is16bit = (obj->handle.Init.DataSize == SPI_DATASIZE_16BIT); + + if (obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) { + uint16_t pos = obj->tx_buff.pos; + spi_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TX, + ((uint8_t *)obj->tx_buff.buffer) + (pos * (is16bit?2:1)), NULL, + obj->tx_buff.length - obj->tx_buff.pos, &obj->fill_symbol); + return; + } else if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) { + uint16_t pos = obj->rx_buff.pos; + + spi_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_RX, + NULL, ((uint8_t *)obj->rx_buff.buffer) + (pos * (is16bit?2:1)), + obj->rx_buff.length - obj->rx_buff.pos, &obj->fill_symbol); + + return; + } + + spi_async_event_t event = { + .transfered = MAX(obj->tx_buff.pos, obj->rx_buff.pos), + .error = (error != HAL_SPI_ERROR_NONE) + }; + spi_async_handler_f handler = obj->handler; + void *ctx = obj->ctx; + + handler(obj, ctx, &event); - return length; + obj->handler = NULL; + obj->ctx = NULL; + + // enable the interrupt + NVIC_DisableIRQ(obj->spiIRQ); + NVIC_ClearPendingIRQ(obj->spiIRQ); + } } // asynchronous API -void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint) +bool spi_transfer_async(spi_t *obj, const void *tx, uint32_t tx_length, void *rx, uint32_t rx_length, + const void *fill_symbol, spi_async_handler_f handler, void *ctx, DMAUsage hint) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); @@ -581,7 +700,7 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, // don't do anything, if the buffers aren't valid if (!use_tx && !use_rx) { - return; + return false; } // copy the buffers to the SPI object @@ -595,79 +714,23 @@ void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, obj->rx_buff.pos = 0; obj->rx_buff.width = obj->tx_buff.width; - obj->spi.event = event; + obj->handler = handler; + obj->ctx = ctx; - DEBUG_PRINTF("SPI: Transfer: %u, %u\n", tx_length, rx_length); + DEBUG_PRINTF("SPI: Transfer: %lu, %lu\n", tx_length, rx_length); - // register the thunking handler - IRQn_Type irq_n = spiobj->spiIRQ; - NVIC_SetVector(irq_n, (uint32_t)handler); - - // enable the right hal transfer if (use_tx && use_rx) { - // we cannot manage different rx / tx sizes, let's use smaller one - size_t size = (tx_length < rx_length) ? tx_length : rx_length; - if (tx_length != rx_length) { - DEBUG_PRINTF("SPI: Full duplex transfer only 1 size: %d\n", size); - obj->tx_buff.length = size; - obj->rx_buff.length = size; - } - spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TXRX, tx, rx, size); + uint32_t size = (rx_length < tx_length)? rx_length : tx_length; + spi_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TXRX, tx, rx, size, fill_symbol); } else if (use_tx) { - spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TX, tx, NULL, tx_length); + spi_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_TX, tx, NULL, tx_length, fill_symbol); } else if (use_rx) { - spi_master_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_RX, NULL, rx, rx_length); - } -} - -inline uint32_t spi_irq_handler_asynch(spi_t *obj) -{ - int event = 0; - - // call the CubeF4 handler, this will update the handle - HAL_SPI_IRQHandler(&obj->spi.handle); - - if (obj->spi.handle.State == HAL_SPI_STATE_READY) { - // When HAL SPI is back to READY state, check if there was an error - int error = obj->spi.handle.ErrorCode; - if (error != HAL_SPI_ERROR_NONE) { - // something went wrong and the transfer has definitely completed - event = SPI_EVENT_ERROR | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; - - if (error & HAL_SPI_ERROR_OVR) { - // buffer overrun - event |= SPI_EVENT_RX_OVERFLOW; - } - } else { - // else we're done - event = SPI_EVENT_COMPLETE | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; - } - // enable the interrupt - NVIC_DisableIRQ(obj->spi.spiIRQ); - NVIC_ClearPendingIRQ(obj->spi.spiIRQ); - } - - - return (event & (obj->spi.event | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE)); -} - -uint8_t spi_active(spi_t *obj) -{ - struct spi_s *spiobj = SPI_S(obj); - SPI_HandleTypeDef *handle = &(spiobj->handle); - HAL_SPI_StateTypeDef state = HAL_SPI_GetState(handle); - - switch (state) { - case HAL_SPI_STATE_RESET: - case HAL_SPI_STATE_READY: - case HAL_SPI_STATE_ERROR: - return 0; - default: - return 1; + spi_start_asynch_transfer(obj, SPI_TRANSFER_TYPE_RX, NULL, rx, rx_length, fill_symbol); } + return true; } -void spi_abort_asynch(spi_t *obj) +void spi_transfer_async_abort(spi_t *obj) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32GG/PeripheralPins.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32GG/PeripheralPins.c index f943fee16b7..c74aa5232b3 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32GG/PeripheralPins.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32GG/PeripheralPins.c @@ -117,6 +117,7 @@ MBED_WEAK const PinMap PinMap_PWM[] = { }; /*************SPI**************/ +#if DEVICE_SPI MBED_WEAK const PinMap PinMap_SPI_MOSI[] = { #ifdef USART0_BASE /* USART0 */ @@ -204,6 +205,7 @@ MBED_WEAK const PinMap PinMap_SPI_CS[] = { /* Not connected */ {NC , NC , NC} }; +#endif /************UART**************/ MBED_WEAK const PinMap PinMap_UART_TX[] = { diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32GG11/PeripheralPins.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32GG11/PeripheralPins.c index 96f40fdaab6..5174e8c7c87 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32GG11/PeripheralPins.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32GG11/PeripheralPins.c @@ -415,8 +415,10 @@ MBED_WEAK const PinMap PinMap_SPI_CS[] = { #endif {NC , NC , NC} }; +#endif /************UART**************/ +#if DEVICE_SERIAL MBED_WEAK const PinMap PinMap_UART_TX[] = { #ifdef USART0_BASE {PE10, USART_0, 0}, @@ -472,9 +474,7 @@ MBED_WEAK const PinMap PinMap_UART_TX[] = { #endif {NC , NC , NC} }; -#endif -#if DEVICE_SERIAL MBED_WEAK const PinMap PinMap_UART_RX[] = { #ifdef USART0_BASE {PE11, USART_0, 0}, diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32HG/PeripheralPins.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32HG/PeripheralPins.c index 2f8e8af5d45..26b50e66993 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32HG/PeripheralPins.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32HG/PeripheralPins.c @@ -83,6 +83,7 @@ MBED_WEAK const PinMap PinMap_PWM[] = { }; /*************SPI**************/ +#if DEVICE_SPI MBED_WEAK const PinMap PinMap_SPI_MOSI[] = { #ifdef USART0_BASE /* USART0 */ @@ -153,6 +154,7 @@ MBED_WEAK const PinMap PinMap_SPI_CS[] = { /* Not connected */ {NC , NC , NC} }; +#endif /************UART**************/ MBED_WEAK const PinMap PinMap_UART_TX[] = { diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32LG/PeripheralPins.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32LG/PeripheralPins.c index f943fee16b7..c74aa5232b3 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32LG/PeripheralPins.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32LG/PeripheralPins.c @@ -117,6 +117,7 @@ MBED_WEAK const PinMap PinMap_PWM[] = { }; /*************SPI**************/ +#if DEVICE_SPI MBED_WEAK const PinMap PinMap_SPI_MOSI[] = { #ifdef USART0_BASE /* USART0 */ @@ -204,6 +205,7 @@ MBED_WEAK const PinMap PinMap_SPI_CS[] = { /* Not connected */ {NC , NC , NC} }; +#endif /************UART**************/ MBED_WEAK const PinMap PinMap_UART_TX[] = { diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32PG/PeripheralPins.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32PG/PeripheralPins.c index c967daad879..55238527f3d 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32PG/PeripheralPins.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32PG/PeripheralPins.c @@ -198,6 +198,7 @@ MBED_WEAK const PinMap PinMap_PWM[] = { }; /*************SPI**************/ +#if DEVICE_SPI MBED_WEAK const PinMap PinMap_SPI_MOSI[] = { #ifdef USART0_BASE /* USART0 */ @@ -368,6 +369,7 @@ MBED_WEAK const PinMap PinMap_SPI_CS[] = { #endif {NC , NC , NC} }; +#endif /************UART**************/ MBED_WEAK const PinMap PinMap_UART_TX[] = { diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32PG12/PeripheralPins.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32PG12/PeripheralPins.c index b34d8b6d6fe..7febab48873 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32PG12/PeripheralPins.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32PG12/PeripheralPins.c @@ -262,6 +262,7 @@ MBED_WEAK const PinMap PinMap_PWM[] = { }; /*************SPI**************/ +#if DEVICE_SPI MBED_WEAK const PinMap PinMap_SPI_MOSI[] = { #ifdef USART0_BASE /* USART0 */ @@ -584,6 +585,7 @@ MBED_WEAK const PinMap PinMap_SPI_CS[] = { #endif {NC , NC , NC} }; +#endif /************UART**************/ MBED_WEAK const PinMap PinMap_UART_TX[] = { diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32WG/PeripheralPins.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32WG/PeripheralPins.c index f943fee16b7..c74aa5232b3 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32WG/PeripheralPins.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32WG/PeripheralPins.c @@ -117,6 +117,7 @@ MBED_WEAK const PinMap PinMap_PWM[] = { }; /*************SPI**************/ +#if DEVICE_SPI MBED_WEAK const PinMap PinMap_SPI_MOSI[] = { #ifdef USART0_BASE /* USART0 */ @@ -204,6 +205,7 @@ MBED_WEAK const PinMap PinMap_SPI_CS[] = { /* Not connected */ {NC , NC , NC} }; +#endif /************UART**************/ MBED_WEAK const PinMap PinMap_UART_TX[] = { diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32ZG/PeripheralPins.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32ZG/PeripheralPins.c index 21944dcaa67..dc15b725e04 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32ZG/PeripheralPins.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFM32ZG/PeripheralPins.c @@ -80,6 +80,7 @@ MBED_WEAK const PinMap PinMap_PWM[] = { }; /*************SPI**************/ +#if DEVICE_SPI MBED_WEAK const PinMap PinMap_SPI_MOSI[] = { #ifdef USART1_BASE /* USART1 */ @@ -119,6 +120,7 @@ MBED_WEAK const PinMap PinMap_SPI_CS[] = { /* Not connected */ {NC , NC , NC} }; +#endif /************UART**************/ MBED_WEAK const PinMap PinMap_UART_TX[] = { diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG1/PeripheralPins.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG1/PeripheralPins.c index 5ac1c632c2e..3f2a12b82de 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG1/PeripheralPins.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG1/PeripheralPins.c @@ -198,6 +198,7 @@ MBED_WEAK const PinMap PinMap_PWM[] = { }; /*************SPI**************/ +#if DEVICE_SPI MBED_WEAK const PinMap PinMap_SPI_MOSI[] = { #ifdef USART0_BASE /* USART0 */ @@ -368,6 +369,7 @@ MBED_WEAK const PinMap PinMap_SPI_CS[] = { #endif {NC , NC , NC} }; +#endif /************UART**************/ MBED_WEAK const PinMap PinMap_UART_TX[] = { diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG12/PeripheralPins.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG12/PeripheralPins.c index f3996813b21..8ea82adb96c 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG12/PeripheralPins.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG12/PeripheralPins.c @@ -265,6 +265,7 @@ MBED_WEAK const PinMap PinMap_PWM[] = { }; /*************SPI**************/ +#if DEVICE_SPI MBED_WEAK const PinMap PinMap_SPI_MOSI[] = { #ifdef USART0_BASE /* USART0 */ @@ -587,6 +588,7 @@ MBED_WEAK const PinMap PinMap_SPI_CS[] = { #endif {NC , NC , NC} }; +#endif /************UART**************/ MBED_WEAK const PinMap PinMap_UART_TX[] = { diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/spi_api.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/spi_api.c index 3a2c9df896d..d007b69ba62 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/spi_api.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/spi_api.c @@ -21,10 +21,10 @@ * ******************************************************************************/ -#include "device.h" -#include "clocking.h" #if DEVICE_SPI +#include "device.h" +#include "clocking.h" #include "mbed_assert.h" #include "mbed_power_mgmt.h" #include "PeripheralPins.h" diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM3H6/spi_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM3H6/spi_api.c index 1ac032fdae2..148155905a2 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM3H6/spi_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM3H6/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "spi_api.h" #include "mbed_error.h" #include "pinmap.h" @@ -257,3 +260,5 @@ uint8_t spi_get_module(spi_t *obj) { return (uint8_t)(obj->module); } + +#endif diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM3HQ/spi_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM3HQ/spi_api.c index 20a6f9c7993..6fe970cc77e 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM3HQ/spi_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM3HQ/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "spi_api.h" #include "mbed_error.h" #include "pinmap.h" @@ -282,3 +285,5 @@ uint8_t spi_get_module(spi_t *obj) { return (uint8_t)(obj->module); } + +#endif diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM46B/spi_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM46B/spi_api.c index e81c1196684..9458eadff7f 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM46B/spi_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM46B/spi_api.c @@ -27,6 +27,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* */ + +#if DEVICE_SPI + #include "spi_api.h" #include "mbed_error.h" #include "pinmap.h" @@ -281,3 +284,5 @@ uint8_t spi_get_module(spi_t *obj) { return (uint8_t)(obj->module); } + +#endif diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/spi_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/spi_api.c index 2ad1f53b2b2..0db2bb315e5 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/spi_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/spi_api.c @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#if DEVICE_SPI + #include "spi_api.h" #include "mbed_error.h" #include "txz_tspi.h" @@ -333,3 +336,5 @@ uint8_t spi_get_module(spi_t *obj) { return (uint8_t)(obj->module); } + +#endif diff --git a/targets/TARGET_WIZNET/TARGET_W7500x/spi_api.c b/targets/TARGET_WIZNET/TARGET_W7500x/spi_api.c index 33aa6798a93..68f99d4d22c 100644 --- a/targets/TARGET_WIZNET/TARGET_W7500x/spi_api.c +++ b/targets/TARGET_WIZNET/TARGET_W7500x/spi_api.c @@ -28,6 +28,8 @@ ******************************************************************************* */ +#if DEVICE_SPI + #include "mbed_assert.h" #include @@ -215,3 +217,4 @@ int spi_busy(spi_t *obj) { return ssp_busy(obj); } +#endif diff --git a/targets/targets.json b/targets/targets.json index beb9db48574..7a6e9ef42ac 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -166,8 +166,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "device_name": "LPC11C24FBD48/301" @@ -193,8 +191,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "default_lib": "small", @@ -225,8 +221,6 @@ "SEMIHOST", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "default_lib": "small", @@ -252,8 +246,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "release_versions": ["2"] @@ -280,8 +272,6 @@ "SEMIHOST", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "device_name": "LPC11U24FHI33/301" @@ -306,9 +296,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "device_name": "LPC11U34FBD48/311" @@ -340,9 +328,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "release_versions": ["2"], @@ -368,9 +354,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "release_versions": ["2"], @@ -396,9 +380,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "device_name": "LPC11U35FHI33/501" @@ -426,9 +408,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "device_name": "LPC11U35FHI33/501" @@ -458,9 +438,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "device_name": "LPC11U37FBD64/501" }, @@ -485,9 +463,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "release_versions": ["2"], @@ -508,8 +484,7 @@ "INTERRUPTIN", "PWMOUT", "SERIAL", - "SLEEP", - "SPI" + "SLEEP" ], "default_lib": "small", "release_versions": ["2"], @@ -531,8 +506,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "release_versions": ["2"], @@ -554,9 +527,7 @@ "INTERRUPTIN", "PWMOUT", "SERIAL", - "SERIAL_FC", - "SPI", - "SPISLAVE" + "SERIAL_FC" ], "default_lib": "small", "release_versions": ["2"], @@ -589,8 +560,6 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "FLASH", "MPU" @@ -636,8 +605,6 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "FLASH", "MPU" @@ -686,8 +653,6 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "FLASH", "MPU" @@ -724,8 +689,6 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "FLASH", "MPU" @@ -746,9 +709,7 @@ "PWMOUT", "SERIAL", "SERIAL_FC", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "device_name": "LPC810M021FN8" @@ -769,9 +730,7 @@ "PWMOUT", "SERIAL", "SERIAL_FC", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "release_versions": ["2"], @@ -792,9 +751,7 @@ "INTERRUPTIN", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "release_versions": ["2"], @@ -814,9 +771,7 @@ "INTERRUPTIN", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "release_versions": ["2"] @@ -846,8 +801,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "MPU" ], @@ -883,8 +836,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "MPU" ], @@ -909,8 +860,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ] }, @@ -933,8 +882,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "MPU" ], @@ -969,9 +916,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "default_lib": "small", "release_versions": ["2"], @@ -1010,8 +955,6 @@ "SEMIHOST", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "default_lib": "small", @@ -1040,8 +983,6 @@ "SEMIHOST", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "release_versions": ["2", "5"], @@ -1068,8 +1009,6 @@ "SEMIHOST", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "device_name": "MKL26Z128xxx4" @@ -1096,8 +1035,6 @@ "SEMIHOST", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "FLASH" ], @@ -1124,8 +1061,6 @@ "SEMIHOST", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "release_versions": ["2"], @@ -1156,8 +1091,6 @@ "SEMIHOST", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "release_versions": ["2"], @@ -1196,8 +1129,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH" @@ -1233,8 +1164,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "default_lib": "std", @@ -1266,8 +1195,6 @@ "SEMIHOST", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "FLASH" ], @@ -1299,8 +1226,6 @@ "SEMIHOST", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH", @@ -1339,12 +1264,9 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "TRNG", - "FLASH", - "802_15_4_PHY" + "FLASH" ], "release_versions": ["2", "5"], "device_name": "MKW24D512xxx5", @@ -1377,8 +1299,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "TRNG", "STDIO_MESSAGES", "FLASH" @@ -1419,9 +1339,6 @@ "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH" @@ -1436,7 +1353,7 @@ }, "K64F": { "supported_form_factors": ["ARDUINO"], - "components_add": ["SD", "FLASHIAP"], + "components_add": [], "core": "Cortex-M4F", "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "extra_labels": [ @@ -1447,8 +1364,7 @@ "KPSDK_MCUS", "KPSDK_CODE", "MCU_K64F", - "Freescale_EMAC", - "PSA" + "Freescale_EMAC" ], "is_disk_virtual": true, "macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED", "MBEDTLS_PSA_CRYPTO_C"], @@ -1473,9 +1389,6 @@ "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG", @@ -1493,7 +1406,6 @@ "inherits": ["K64F"], "extra_labels_add": ["K64F"], "extra_labels_remove": ["FRDM"], - "components_remove": ["SD"], "supported_form_factors": [], "detect_code": ["3105"] }, @@ -1518,7 +1430,6 @@ "TRNG", "SLEEP", "INTERRUPTIN", - "SPI", "I2C", "ANALOGIN", "MPU" @@ -1549,7 +1460,6 @@ "TRNG", "SLEEP", "INTERRUPTIN", - "SPI", "I2C", "ANALOGIN", "MPU" @@ -1586,9 +1496,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE", "STDIO_MESSAGES", "FLASH" ], @@ -1625,9 +1532,6 @@ "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH" @@ -1677,9 +1581,6 @@ "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH" @@ -1721,11 +1622,12 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "TRNG", - "FLASH" + "FLASH", + "SPI", + "SPISLAVE", + "SPI_ASYNCH" ], "release_versions": ["2", "5"], "device_name": "MK66FN2M0xxx18", @@ -1736,7 +1638,7 @@ }, "K82F": { "supported_form_factors": ["ARDUINO"], - "components_add": ["SPIF", "FLASHIAP"], + "components_add": [], "core": "Cortex-M4F", "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "FRDM"], @@ -1759,8 +1661,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH", @@ -1772,7 +1672,6 @@ "UBRIDGE": { "inherits": ["K82F"], "extra_labels_remove": ["FRDM"], - "components_remove": ["SPIF"], "device_has_remove": ["QSPI"], "supported_form_factors": [] }, @@ -1825,9 +1724,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES" ] }, @@ -1865,8 +1761,6 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "MPU" ], @@ -1904,8 +1798,6 @@ "PORTOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "FLASH", "MPU" @@ -1939,8 +1831,6 @@ "PORTOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", "STDIO_MESSAGES", "FLASH", "TRNG", @@ -2439,7 +2329,7 @@ }, "USI_WM_BN_BM_22": { "inherits": ["FAMILY_STM32"], - "components_add": ["SPIF", "FLASHIAP"], + "components_add": ["FLASHIAP"], "core": "Cortex-M4F", "extra_labels_add": [ "STM32F4", @@ -2618,7 +2508,10 @@ "SERIAL_FC", "TRNG", "FLASH", - "MPU" + "MPU", + "SPI", + "SPISLAVE", + "SPI_ASYNCH" ], "detect_code": ["0796"], "release_versions": ["2", "5"], @@ -3356,7 +3249,6 @@ "detect_code": ["9015"], "release_versions": ["2", "5"], "device_name" : "STM32F439VI", - "components_add": ["SD"], "bootloader_supported": true, "overrides": { "network-default-interface-type": "CELLULAR" @@ -4190,9 +4082,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ] }, "MCU_NRF51_16K_BASE": { @@ -4436,9 +4326,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "release_versions": ["2"], "device_name": "nRF51822_xxAA" @@ -4472,10 +4360,7 @@ "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE" + "SLEEP" ], "device_name": "nRF51822_xxAC" }, @@ -4587,10 +4472,7 @@ "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE" + "SLEEP" ], "device_name": "nRF51822_xxAA", "release_versions": ["5"], @@ -4630,10 +4512,7 @@ "PWMOUT", "SERIAL", "SERIAL_ASYNCH", - "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE" + "SLEEP" ], "detect_code": ["1019"], "release_versions": ["2", "5"], @@ -4665,8 +4544,6 @@ "PORTOUT", "SERIAL", "SERIAL_FC", - "SPI", - "SPISLAVE", "TSC" ] }, @@ -4692,8 +4569,6 @@ "PORTOUT", "SERIAL", "SERIAL_FC", - "SPI", - "SPISLAVE", "TSC", "MPU" ], @@ -4717,8 +4592,6 @@ "PORTOUT", "SERIAL", "SERIAL_FC", - "SPI", - "SPISLAVE", "TSC", "MPU" ], @@ -4742,8 +4615,6 @@ "PORTOUT", "SERIAL", "SERIAL_FC", - "SPI", - "SPISLAVE", "TSC", "MPU" ], @@ -4767,8 +4638,6 @@ "PORTOUT", "SERIAL", "SERIAL_FC", - "SPI", - "SPISLAVE", "TSC", "MPU" ], @@ -4792,8 +4661,6 @@ "PORTOUT", "SERIAL", "SERIAL_FC", - "SPI", - "SPISLAVE", "TSC", "MPU" ], @@ -4814,8 +4681,6 @@ "PORTOUT", "SERIAL", "SERIAL_FC", - "SPI", - "SPISLAVE", "TSC", "MPU" ] @@ -4838,8 +4703,6 @@ "PORTOUT", "SERIAL", "SERIAL_FC", - "SPI", - "SPISLAVE", "TSC", "MPU" ], @@ -4866,7 +4729,6 @@ "RTC", "SERIAL", "SLEEP", - "SPI", "TRNG", "USTICKER", "MPU" @@ -4909,7 +4771,6 @@ "PORTOUT", "SERIAL", "SLEEP", - "SPI", "MPU" ], "features": ["BLE"], @@ -4938,9 +4799,6 @@ "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES" ], "program_cycle_s": 2, @@ -4952,7 +4810,6 @@ "inherits": ["RZ_A1XX"], "supported_form_factors": ["ARDUINO"], "extra_labels_add": ["RZA1H", "MBRZA1H", "RZ_A1_EMAC"], - "components_add": ["SD"], "device_has_add": ["EMAC", "FLASH", "LPTICKER"], "release_versions": ["2", "5"], "device_name": "R7S72100", @@ -4968,7 +4825,6 @@ "inherits": ["RZ_A1XX"], "supported_form_factors": ["ARDUINO"], "extra_labels_add": ["RZA1UL", "MBRZA1LU"], - "components_add": ["SD"], "device_has_add": ["TRNG", "FLASH", "LPTICKER"], "device_has_remove": ["ETHERNET"], "release_versions": ["2", "5"], @@ -4996,7 +4852,6 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", "STDIO_MESSAGES" ], "features": ["BLE"], @@ -5020,7 +4875,6 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", "STDIO_MESSAGES" ], "release_versions": ["2", "5"] @@ -5041,8 +4895,6 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", - "SPI_ASYNCH", "STDIO_MESSAGES" ], "features": ["BLE"], @@ -5071,7 +4923,6 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", "STDIO_MESSAGES", "USTICKER" ], @@ -5101,7 +4952,6 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", "STDIO_MESSAGES", "USTICKER" ], @@ -5126,7 +4976,6 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", "STDIO_MESSAGES", "USTICKER" ], @@ -5174,7 +5023,6 @@ "PWMOUT", "SERIAL", "SERIAL_FC", - "SPI", "STDIO_MESSAGES", "USTICKER", "MPU" @@ -5222,9 +5070,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH", @@ -5299,9 +5144,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH", @@ -5377,9 +5219,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH", @@ -5452,9 +5291,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER" ], @@ -5525,9 +5361,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER" ], @@ -5599,9 +5432,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH", @@ -5698,9 +5528,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH", @@ -5768,9 +5595,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH", @@ -5845,9 +5669,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", @@ -5933,9 +5754,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", @@ -6014,9 +5832,6 @@ "SERIAL", "SERIAL_ASYNCH", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", @@ -6089,8 +5904,6 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "release_versions": ["2", "5"] @@ -6114,8 +5927,6 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "release_versions": ["2", "5"] @@ -6138,8 +5949,6 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SPI", - "SPISLAVE", "STDIO_MESSAGES" ], "release_versions": ["2", "5"] @@ -6169,10 +5978,7 @@ "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH" + "SLEEP" ], "release_versions": ["2"], "device_name": "ATSAMR21G18A" @@ -6203,10 +6009,7 @@ "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH" + "SLEEP" ], "release_versions": ["2"], "device_name": "ATSAMD21J18A" @@ -6237,10 +6040,7 @@ "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH" + "SLEEP" ], "release_versions": ["2"], "device_name": "ATSAMD21G18A" @@ -6271,10 +6071,7 @@ "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH" + "SLEEP" ], "device_name": "ATSAML21J18A" }, @@ -6306,9 +6103,6 @@ "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "MPU" ], "default_lib": "std", @@ -6380,9 +6174,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ] }, "MCU_NRF51_16K_UNIFIED_S130": { @@ -6422,10 +6214,7 @@ "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE" + "SLEEP" ], "release_versions": ["2", "5"], "device_name": "nRF51822_xxAA" @@ -6446,10 +6235,7 @@ "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE" + "SLEEP" ], "detect_code": ["3103"], "release_versions": ["2", "5"], @@ -6470,10 +6256,7 @@ "PWMOUT", "SERIAL", "SERIAL_ASYNCH", - "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE" + "SLEEP" ], "release_versions": ["2", "5"] }, @@ -6492,9 +6275,7 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SLEEP", - "SPI", - "SPISLAVE" + "SLEEP" ], "device_name": "nRF51822_xxAC" }, @@ -6526,8 +6307,6 @@ "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", - "SPI", - "SPI_ASYNCH", "SYSTICK_CLK_OFF_DURING_SLEEP", "TRNG", "USTICKER" @@ -6648,8 +6427,6 @@ "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", - "SPI", - "SPI_ASYNCH", "SYSTICK_CLK_OFF_DURING_SLEEP", "TRNG", "USTICKER", @@ -6763,9 +6540,6 @@ "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "TRNG", "CAN", "FLASH", @@ -6832,9 +6606,7 @@ "SERIAL", "SERIAL_FC", "SLEEP", - "SPI", "TRNG", - "SPISLAVE", "802_15_4_PHY", "MPU" ], @@ -6891,9 +6663,6 @@ "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "CAN", "FLASH", "MPU" @@ -6956,10 +6725,7 @@ "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", - "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH" + "SLEEP" ], "release_versions": ["5"], "device_name": "NANO130KE3BN" @@ -7028,7 +6794,6 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SPI", "TRNG", "FLASH" ], @@ -7091,10 +6856,7 @@ "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SLEEP", - "SPI", - "SPI_ASYNCH", - "SPISLAVE" + "SLEEP" ], "release_versions": ["2"], "device_name": "nRF51822_xxAC" @@ -7259,9 +7021,6 @@ "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "TRNG", "FLASH", "CAN", @@ -7328,9 +7087,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "STDIO_MESSAGES", "MPU" ], @@ -7362,7 +7118,6 @@ "PWMOUT", "SERIAL", "SERIAL_FC", - "SPI", "I2C", "STDIO_MESSAGES", "TRNG", @@ -7398,8 +7153,6 @@ "PORTOUT", "SERIAL", "SERIAL_FC", - "SPI", - "SPISLAVE", "TSC", "USTICKER" ], @@ -7493,9 +7246,6 @@ "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", - "SPI", - "SPISLAVE", - "SPI_ASYNCH", "TRNG", "FLASH", "MPU" @@ -7523,7 +7273,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", "I2C", "I2CSLAVE", "STDIO_MESSAGES", @@ -7549,7 +7298,6 @@ "PORTOUT", "PWMOUT", "SERIAL", - "SPI", "I2C", "I2CSLAVE", "STDIO_MESSAGES", @@ -7585,8 +7333,6 @@ "ANALOGOUT", "I2C", "I2C_ASYNCH", - "SPI", - "SPI_ASYNCH", "STDIO_MESSAGES", "LPTICKER", "SLEEP", @@ -7681,7 +7427,6 @@ "PWMOUT", "SERIAL", "SLEEP", - "SPI", "I2C", "I2CSLAVE", "STDIO_MESSAGES", @@ -7698,7 +7443,7 @@ "extra_labels": ["RDA", "UNO_91H", "FLASH_CMSIS_ALGO"], "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "macros": ["TWO_RAM_REGIONS", "CMSIS_NVIC_VIRTUAL", "CMSIS_NVIC_VIRTUAL_HEADER_FILE=\"RDA5981_nvic_virtual.h\""], - "device_has": ["USTICKER", "PORTIN", "PORTOUT", "PORTINOUT", "INTERRUPTIN", "SERIAL", "STDIO_MESSAGES", "PWMOUT", "SPI", "SLEEP", "ANALOGIN", "FLASH", "TRNG", "MPU"], + "device_has": ["USTICKER", "PORTIN", "PORTOUT", "PORTINOUT", "INTERRUPTIN", "SERIAL", "STDIO_MESSAGES", "PWMOUT", "SLEEP", "ANALOGIN", "FLASH", "TRNG", "MPU"], "release_versions": ["2", "5"] }, "UNO_91H": { diff --git a/tools/test/examples/examples.json b/tools/test/examples/examples.json index 95b3e4630fa..09e0fd4f99b 100644 --- a/tools/test/examples/examples.json +++ b/tools/test/examples/examples.json @@ -131,10 +131,10 @@ "mbed": [], "test-repo-source": "github", "features" : [], - "targets" : ["DISCO_L072CZ_LRWAN1", "MTB_MTS_XDOT", "MTS_MDOT_F411RE"], + "targets" : [], "toolchains" : [], "exporters": [], - "compile" : true, + "compile" : false, "export": false, "auto-update" : true }, @@ -266,10 +266,8 @@ ], "test-repo-source": "github", "features" : [], - "targets" : ["DISCO_F469NI", "DISCO_F746NG", "K66F", - "NUCLEO_F429ZI", "NUCLEO_F439ZI", "NUCLEO_F746ZG", - "NUCLEO_F756ZG", "NUCLEO_F767ZI", - "NUMAKER_PFM_NUC472", "UBLOX_EVK_ODIN_W2"], + "targets" : ["K66F", + "NUCLEO_F429ZI"], "toolchains" : [], "exporters": [], "compile" : true, @@ -284,7 +282,7 @@ ], "test-repo-source": "github", "features" : [], - "targets" : ["K64F", "NUCLEO_F429ZI", "UBLOX_EVK_ODIN_W2"], + "targets" : ["NUCLEO_F429ZI"], "toolchains" : [], "exporters": [], "compile" : true, @@ -312,11 +310,11 @@ ], "test-repo-source": "mbed", "features" : [], - "targets" : ["NUCLEO_F401RE", "DISCO_L475VG_IOT01A"], + "targets" : [], "toolchains" : [], "exporters": [], - "compile" : true, - "export": true, + "compile" : false, + "export": false, "auto-update" : true }, { @@ -325,11 +323,11 @@ "mbed": [], "test-repo-source": "github", "features" : [], - "targets" : ["K64F"], + "targets" : [], "toolchains" : [], "exporters": [], - "compile" : true, - "export": true, + "compile" : false, + "export": false, "auto-update" : true }, {