This program is derived from SPIrtc, which is of a more exploratory nature, using a former version of module SPIdev.1 This new version is now based on the updated module SPIdev, and basically demonstrates how to use a peripheral device connected via SPI, namely the Maxim DS3234 real-time clock.

The program makes use of the kernel-v1 to run two threads on core 0. One thread periodically reads the date and time from the clock, and prints it to the serial terminal. It also reads the so called timestamp, which is the date and time encoded in a single 32 bit value, and prints the timestamp followed by the date and time decoded from it.

A special variant of module RTCds3234test in the example program shows how to dynamically adjust some SPI parameters on the fly.

c0-t1   24  6  3   15 41 53  1636235893   24  6  3   15 41 53
c0-t1   24  6  3   15 41 54  1636235894   24  6  3   15 41 54
c0-t1   24  6  3   15 41 55  1636235895   24  6  3   15 41 55
c0-t1   24  6  3   15 41 56  1636235896   24  6  3   15 41 56
c0-t1   24  6  3   15 41 57  1636235897   24  6  3   15 41 57
c0-t1   24  6  3   15 41 58  1636235898   24  6  3   15 41 58
c0-t1   24  6  3   15 41 59  1636235899   24  6  3   15 41 59
c0-t1   24  6  3   15 42  0  1636235904   24  6  3   15 42  0
c0-t1   24  6  3   15 42  1  1636235905   24  6  3   15 42  1


The program is implemented in one module SPIrtc2.mod:

  • Thread 0: heartbeat blinker, also writes a counter value to the eight LEDs via module LEDext.
  • Thread 1: periodically reads the values from the real-time clock peripheral, and prints the results, as outlined above.

Module SPIdev

Module SPIdev defines and implements a representation of the basic device on the RP2040 chip. It mainly serves to initialise the corresponding data structure SPIdev.Device with all data required to operate the device, eg. from SPIdata, such as register addresses, and to configure and enable the SPI hardware of the RP2040.

An SPI Device can talk to multiple connected peripherals, selected via CS (chip select), and to each peripheral using a different configuration. The main configuration parameters of SPI are

  • serial clock rate,
  • serial clock polarity and phase (cpol, cpha), and
  • data size (8 or 16 bits).

SPIdev.Device also provides parameter txShift value, ie. the “dummy” transmit data to receive data.2

SPIdev provides the “usual” procedures Init, Configure, and Enable to get the SPI hardware up and running. The configuration of the GPIO pins and pads used – MOSI, MISO, SCLK, and CS – must be done by the client module or program, in this case by module SPIrtc2.

If the chip select signal is to be operated via SIO (see section Chip Select Options (CS) in SPIrtc), this must be done by the client as well. SPIdev does not provide support for chip selection. See module RTCds3234.mod for an example.

In case a peripheral connected via SPI requires different configuration parameters than set up via SPIdev.Configure, a corresponding adjusted RunCfg can be derived, and switched to and from dynamically.

Currently, SPIdev supports two such configuration parameter adaptations:

  • serial clock rate
  • txShift value

Other adjustable parameters may be added in the future. For example, some SPI-driven displays expect so called commands to be sent as 8 bit values, but allow to transfer data as 16 or 32 bits. A dynamic switch between data sizes could be useful (the RP2040’s SPI device allows data sizes between 4 and 16 bits).

Module RTCds3234test in the example folder (artificially) demonstrates this, dynamically switching between different configurations for the three SPI transactions for reading the time, date, and timestamp.

Module SPIdata

Module SPIdata uses the device definition SPIdev.Device to transmit and receive data from the peripheral connected to the RP2040’s device, ie. the real-time clock in the example program.

The RP2040’s SPI devices always use a transmit and a receive FIFO buffer, 16 bits wide and 8 entries deep. The transmit FIFO is written from software, and emptied by the SPI hardware, the receive FIFO is written by the hardware and read from software. Each data transmit FIFO out causes a receive FIFO in with an SPI peripheral connected correctly. The software must ensure that writes and reads are balanced, on both the software and hardware ends of each FIFO, and in particular ensure that the receive FIFO does not overflow by data received via MISO from the peripheral. See the implementation of SPIdata.GetBytes and SPIdata.PutBytes.


Using RTCds3234.mod

Below are the SPI signals for one cycle of thread 1 (seeSPIrtc2.tc1), with the program compiled as in the repository:

  • red: CS signal (oscilloscope trigger source, negative edge)
  • yellow: serial clock (1 MHz)
  • blue: MOSI
  • green: MISO

Three SPI transactions:

  • Read time: write address 0, read three registers.
  • Read date: write address 4, read three registers.
  • Read timestamp: write address 0, read seven registers (cut off in the screenshot).

Using RTCds3234test.mod

If we compile the test program with RTC = RTCds3234test, we get this signal trace:

  • The serial clock rate for the transaction to read the date is now 2 MHz in lieu of 1 MHz.
  • The txShift value for the transactions to read the time and the timestamp is 0AAH in lieu of 0F0H.

Peripheral Connections

The GPIO pins used for the wiring of the DS3234 real-time clock to the RP2040 are listed in module SPIrtc2.

Output Terminal

See Set-up, one-terminal set-up.

Build and Run

Build module SPIrtc2 with Astrobe, and create and upload the UF2 file using abin2uf2.

Set Astrobe’s memory options as listed, and the library search path as explained. The program has been developed and tested with kernel-v1, which should be reflected in the library search path.


  1. This version of module SPIdev is still available in the example project folder. ↩︎

  2. Many SPI peripherals don’t care about this value, but some do, such as SD cards. For the DS3234 we use values that display well on an oscilloscope. 00H or 0FFH would not. ↩︎