diff --git a/cores/rp2040/Arduino.h b/cores/rp2040/Arduino.h
index 8efad0b70..5d850a5b1 100644
--- a/cores/rp2040/Arduino.h
+++ b/cores/rp2040/Arduino.h
@@ -170,6 +170,9 @@ constexpr uint64_t __bitset(const int (&a)[N], size_t i = 0U) {
#define __FIRSTANALOGGPIO 26
#endif
+// For peripherals where a pin may be not used
+#define NOPIN ((pin_size_t) 0xff)
+
#ifdef __cplusplus
using namespace arduino;
#endif
diff --git a/cores/rp2040/SerialPIO.h b/cores/rp2040/SerialPIO.h
index 3b7d0cf87..fd92d588a 100644
--- a/cores/rp2040/SerialPIO.h
+++ b/cores/rp2040/SerialPIO.h
@@ -29,7 +29,6 @@ extern "C" typedef struct uart_inst uart_inst_t;
class SerialPIO : public arduino::HardwareSerial {
public:
- static const pin_size_t NOPIN = 0xff; // Use in constructor to disable RX or TX unit
SerialPIO(pin_size_t tx, pin_size_t rx, size_t fifoSize = 32);
~SerialPIO();
diff --git a/docs/piouart.rst b/docs/piouart.rst
index 78128815c..5e141698f 100644
--- a/docs/piouart.rst
+++ b/docs/piouart.rst
@@ -12,13 +12,13 @@ are supported, as well as data sizes from 5- to 8-bits. Fifosize, if not
specified, defaults to 32 bytes.
To instantiate only a serial transmit or receive unit, pass in
-``SerialPIO::NOPIN`` as the ``txpin`` or ``rxpin``.
+``NOPIN`` as the ``txpin`` or ``rxpin``.
For example, to make a transmit-only port on GP16
.. code:: cpp
- SerialPIO transmitter( 16, SerialPIO::NOPIN );
+ SerialPIO transmitter( 16, NOPIN );
For detailed information about the Serial ports, see the
Arduino `Serial Reference `_ .
diff --git a/docs/spi.rst b/docs/spi.rst
index fdfd80bcc..36942d742 100644
--- a/docs/spi.rst
+++ b/docs/spi.rst
@@ -16,6 +16,9 @@ SPI pinouts can be set **before SPI.begin()** using the following calls:
Note that the ``CS`` pin can be hardware or software controlled by the sketch.
When software controlled, the ``setCS()`` call is ignored.
+Passing in ``NOPIN`` to either ``setRX`` or ``setTX`` will disable SPI on that
+interface, making it behave as a unidirectional (output- or input-only SPI interface.
+
The Arduino `SPI documentation `_ gives
a detailed overview of the library, except for the following RP2040-specific
changes:
diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp
index 95935e72e..e06c8843e 100644
--- a/libraries/SPI/src/SPI.cpp
+++ b/libraries/SPI/src/SPI.cpp
@@ -281,6 +281,11 @@ bool SPIClassRP2040::setRX(pin_size_t pin) {
return true;
}
+ if (!_running && (pin == NOPIN)) {
+ _RX = pin;
+ return true;
+ }
+
if (_running) {
panic("FATAL: Attempting to set SPI%s.RX while running", spi_get_index(_spi) ? "1" : "");
} else {
@@ -362,6 +367,11 @@ bool SPIClassRP2040::setTX(pin_size_t pin) {
return true;
}
+ if (!_running && (pin == NOPIN)) {
+ _TX = pin;
+ return true;
+ }
+
if (_running) {
panic("FATAL: Attempting to set SPI%s.TX while running", spi_get_index(_spi) ? "1" : "");
} else {
@@ -372,13 +382,22 @@ bool SPIClassRP2040::setTX(pin_size_t pin) {
void SPIClassRP2040::begin(bool hwCS) {
DEBUGSPI("SPI::begin(%d), rx=%d, cs=%d, sck=%d, tx=%d\n", hwCS, _RX, _CS, _SCK, _TX);
- gpio_set_function(_RX, GPIO_FUNC_SPI);
+
+ if ((_RX == NOPIN) && (_TX == NOPIN)) {
+ panic("SPI%s: TX and RX assigned to NOPIN", spi_get_index(_spi) ? "1" : "");
+ }
+
+ if (_RX != NOPIN) {
+ gpio_set_function(_RX, GPIO_FUNC_SPI);
+ }
_hwCS = hwCS;
if (hwCS) {
gpio_set_function(_CS, GPIO_FUNC_SPI);
}
gpio_set_function(_SCK, GPIO_FUNC_SPI);
- gpio_set_function(_TX, GPIO_FUNC_SPI);
+ if (_TX != NOPIN) {
+ gpio_set_function(_TX, GPIO_FUNC_SPI);
+ }
// Give a default config in case user doesn't use beginTransaction
beginTransaction(_spis);
endTransaction();
@@ -391,12 +410,16 @@ void SPIClassRP2040::end() {
_initted = false;
spi_deinit(_spi);
}
- gpio_set_function(_RX, GPIO_FUNC_SIO);
+ if (_RX != NOPIN) {
+ gpio_set_function(_RX, GPIO_FUNC_SIO);
+ }
if (_hwCS) {
gpio_set_function(_CS, GPIO_FUNC_SIO);
}
gpio_set_function(_SCK, GPIO_FUNC_SIO);
- gpio_set_function(_TX, GPIO_FUNC_SIO);
+ if (_TX != NOPIN) {
+ gpio_set_function(_TX, GPIO_FUNC_SIO);
+ }
_spis = SPISettings(0, LSBFIRST, SPI_MODE0);
}
diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h
index 27c299bd0..8d159a8bf 100644
--- a/libraries/SPI/src/SPI.h
+++ b/libraries/SPI/src/SPI.h
@@ -31,21 +31,21 @@
class SPIClassRP2040 : public arduino::HardwareSPI {
public:
/**
- @brief Create a PIO-based SPI instance, pins can be changed before begin() call
+ @brief Create a PIO-based SPI instance, pins can be changed before begin() call
- @param [in] spi SPI hardware instance (spi0/spi1)
- @param [in] rx MISO GPIO
- @param [in] cs CS GPIO
- @param [in] sck SCK GPIO
- @param [in] tx MOSI GPIO
+ @param [in] spi SPI hardware instance (spi0/spi1)
+ @param [in] rx MISO GPIO
+ @param [in] cs CS GPIO
+ @param [in] sck SCK GPIO
+ @param [in] tx MOSI GPIO
*/
SPIClassRP2040(spi_inst_t *spi, pin_size_t rx, pin_size_t cs, pin_size_t sck, pin_size_t tx);
/**
- @brief Send an 8-bit byte of data and return read-back 8-bit value
+ @brief Send an 8-bit byte of data and return read-back 8-bit value
- @param [in] data Data to send
- @returns Read back byte from SPI interface
+ @param [in] data Data to send
+ @returns Read back byte from SPI interface
*/
byte transfer(uint8_t data) override;
@@ -67,11 +67,11 @@ class SPIClassRP2040 : public arduino::HardwareSPI {
void transfer(void *buf, size_t count) override;
/**
- @brief Sends one buffer and receives into another under a single CS. Can set rx or txbuf to nullptr
+ @brief Sends one buffer and receives into another under a single CS. Can set rx or txbuf to nullptr
- @param [in] txbuf Buffer to transmit or nullptr to send 0s
- @param [out] rxbuf Buffer to read back into or nullptr to ignore returned data
- @param [in] count Numbner of bytes to transmit/receive
+ @param [in] txbuf Buffer to transmit or nullptr to send 0s
+ @param [out] rxbuf Buffer to read back into or nullptr to ignore returned data
+ @param [in] count Numbner of bytes to transmit/receive
*/
void transfer(const void *txbuf, void *rxbuf, size_t count) override;
@@ -108,134 +108,134 @@ class SPIClassRP2040 : public arduino::HardwareSPI {
/**
- @brief Begin an SPI transaction, sets SPI speed and masks necessary interrupts
+ @brief Begin an SPI transaction, sets SPI speed and masks necessary interrupts
- @param [in] SPISettings SPI configuration parameters, including the clock speed
+ @param [in] SPISettings SPI configuration parameters, including the clock speed
*/
void beginTransaction(SPISettings settings) override;
/**
- @brief Ends an SPI transaction, unmasks and masked GPIO interrupts
+ @brief Ends an SPI transaction, unmasks and masked GPIO interrupts
*/
void endTransaction(void) override;
/**
- @brief Sets the MISO(RX) pin. Call before begin()
+ @brief Sets the MISO(RX) pin. Call before begin()
- @param [in] pin The GPIO number to assign to
- @returns True on success
+ @param [in] pin The GPIO number to assign to or NOPIN
+ @returns True on success
*/
bool setRX(pin_size_t pin);
/**
- @brief Sets the MISO(RX) pin. Call before begin()
+ @brief Sets the MISO(RX) pin. Call before begin()
- @param [in] pin The GPIO number to assign to
- @returns True on success
+ @param [in] pin The GPIO number to assign to
+ @returns True on success
*/
inline bool setMISO(pin_size_t pin) {
return setRX(pin);
}
/**
- @brief Sets the CS pin. Call before begin()
+ @brief Sets the CS pin. Call before begin()
- @param [in] pin The GPIO number to assign to
- @returns True on success
+ @param [in] pin The GPIO number to assign to
+ @returns True on success
*/
bool setCS(pin_size_t pin);
/**
- @brief Sets the SCK pin. Call before begin()
+ @brief Sets the SCK pin. Call before begin()
- @param [in] pin The GPIO number to assign to
- @returns True on success
+ @param [in] pin The GPIO number to assign to
+ @returns True on success
*/
bool setSCK(pin_size_t pin);
/**
- @brief Sets the MOSI(TX) pin. Call before begin()
+ @brief Sets the MOSI(TX) pin. Call before begin()
- @param [in] pin The GPIO number to assign to
- @returns True on success
+ @param [in] pin The GPIO number to assign to
+ @returns True on success
*/
bool setTX(pin_size_t pin);
/**
- @brief Sets the MOSI(TX) pin. Call before begin()
+ @brief Sets the MOSI(TX) pin. Call before begin()
- @param [in] pin The GPIO number to assign to
- @returns True on success
+ @param [in] pin The GPIO number to assign to or NOPIN
+ @returns True on success
*/
inline bool setMOSI(pin_size_t pin) {
return setTX(pin);
}
/**
- @brief Call once to init/deinit SPI class, select pins, etc.
+ @brief Call once to init/deinit SPI class, select pins, etc.
*/
virtual void begin() override {
begin(false);
}
/**
- @brief Call once to init/deinit SPI class, select pins, etc.
+ @brief Call once to init/deinit SPI class, select pins, etc.
- @param [in] hwCS Pass in true to enable HW-controlled CS. Otherwise application needs to assert/deassert CS.
+ @param [in] hwCS Pass in true to enable HW-controlled CS. Otherwise application needs to assert/deassert CS.
*/
void begin(bool hwCS);
/**
- @brief Call to deinit and disable the SPI interface.
+ @brief Call to deinit and disable the SPI interface.
*/
void end() override;
/**
- @brief Deprecated, do not use
+ @brief Deprecated, do not use
- @param [in] order Deprecated
+ @param [in] order Deprecated
*/
void setBitOrder(BitOrder order) __attribute__((deprecated));
/**
- @brief Deprecated, do not use
+ @brief Deprecated, do not use
- @param [in] order Deprecated
+ @param [in] order Deprecated
*/
void setDataMode(uint8_t uc_mode) __attribute__((deprecated));
/**
- @brief Deprecated, do not use
+ @brief Deprecated, do not use
- @param [in] order Deprecated
+ @param [in] order Deprecated
*/
void setClockDivider(uint8_t uc_div) __attribute__((deprecated));
/**
- @brief Ensure specific GPIO interrupt is disabled during and SPI transaction to protect against re-entrancy. Multiple GPIOs supported by multiple calls.
+ @brief Ensure specific GPIO interrupt is disabled during and SPI transaction to protect against re-entrancy. Multiple GPIOs supported by multiple calls.
- @param [in] interruptNumber GPIO pin to mask
+ @param [in] interruptNumber GPIO pin to mask
*/
virtual void usingInterrupt(int interruptNumber) override {
_helper.usingInterrupt(interruptNumber);
}
/**
- @brief Remove a GPIO from the masked-during-transaction list.
+ @brief Remove a GPIO from the masked-during-transaction list.
- @param [in] interruptNumber GPIO pin to unmask
+ @param [in] interruptNumber GPIO pin to unmask
*/
virtual void notUsingInterrupt(int interruptNumber) override {
_helper.notUsingInterrupt(interruptNumber);
}
/**
- @brief Deprecated, do not use
+ @brief Deprecated, do not use
*/
virtual void attachInterrupt() override __attribute__((deprecated)) { /* noop */ }
/**
- @brief Deprecated, do not use
+ @brief Deprecated, do not use
*/
virtual void detachInterrupt() override __attribute__((deprecated)) { /* noop */ }