Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cores/rp2040/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 0 additions & 1 deletion cores/rp2040/SerialPIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
4 changes: 2 additions & 2 deletions docs/piouart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://www.arduino.cc/reference/en/language/functions/communication/serial/>`_ .
Expand Down
3 changes: 3 additions & 0 deletions docs/spi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://docs.arduino.cc/language-reference/en/functions/communication/SPI/>`_ gives
a detailed overview of the library, except for the following RP2040-specific
changes:
Expand Down
31 changes: 27 additions & 4 deletions libraries/SPI/src/SPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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();
Expand All @@ -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);
}

Expand Down
100 changes: 50 additions & 50 deletions libraries/SPI/src/SPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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 */ }

Expand Down
Loading