Skip to content

Commit

Permalink
rp2040: Add spi slave example (#391)
Browse files Browse the repository at this point in the history
  • Loading branch information
Grazfather authored Feb 17, 2025
1 parent b3c6cfd commit 18cbbec
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 70 deletions.
3 changes: 2 additions & 1 deletion examples/raspberrypi/rp2xxx/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ pub fn build(b: *std.Build) void {
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_pwm", .file = "src/rp2040_only/pwm.zig" },
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_random", .file = "src/rp2040_only/random.zig" },
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_rtc", .file = "src/rp2040_only/rtc.zig" },
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_spi-host", .file = "src/rp2040_only/spi_host.zig" },
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_uart-echo", .file = "src/rp2040_only/uart_echo.zig" },
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_uart-log", .file = "src/rp2040_only/uart_log.zig" },
.{ .target = mb.ports.rp2xxx.boards.raspberrypi.pico, .name = "pico_usb-hid", .file = "src/rp2040_only/usb_hid.zig" },
Expand All @@ -40,6 +39,8 @@ pub fn build(b: *std.Build) void {
};

const chip_agnostic_examples: []const ChipAgnosticExample = &.{
.{ .name = "spi-master", .file = "src/spi_master.zig" },
.{ .name = "spi-slave", .file = "src/spi_slave.zig" },
.{ .name = "squarewave", .file = "src/squarewave.zig" },
.{ .name = "ws2812", .file = "src/ws2812.zig" },
.{ .name = "blinky", .file = "src/blinky.zig" },
Expand Down
67 changes: 0 additions & 67 deletions examples/raspberrypi/rp2xxx/src/rp2040_only/spi_host.zig

This file was deleted.

37 changes: 37 additions & 0 deletions examples/raspberrypi/rp2xxx/src/spi_master.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const std = @import("std");
const microzig = @import("microzig");

const rp2xxx = microzig.hal;
const time = rp2xxx.time;
const gpio = rp2xxx.gpio;

const BUF_LEN = 0x100;
const spi = rp2xxx.spi.instance.SPI0;

// These may change depending on which GPIO pins you have your SPI device routed to.
const CS_PIN = 17;
const SCK_PIN = 18;
// NOTE: rp2xxx doesn't label pins as MOSI/MISO. Instead a pin is always for
// either receiving or transmitting SPI data, no matter whether the chip is in
// master or slave mode.
const TX_PIN = 19;

// Communicate with another RP2040 over spi
pub fn main() !void {
// Set pin functions for CS, SCK, RX
const csn = rp2xxx.gpio.num(CS_PIN);
const mosi = rp2xxx.gpio.num(TX_PIN);
const sck = rp2xxx.gpio.num(SCK_PIN);
inline for (&.{ csn, mosi, sck }) |pin| {
pin.set_function(.spi);
}

try spi.apply(.{ .clock_config = rp2xxx.clock_config });
var out_buf: [BUF_LEN]u8 = .{ 'h', 'e', 'y', ' ', 'y', 'o', 'u', '!' } ** (BUF_LEN / 8);

while (true) {
std.log.info("Sending some data\n", .{});
spi.write_blocking(u8, &out_buf);
time.sleep_ms(1 * 1000);
}
}
62 changes: 62 additions & 0 deletions examples/raspberrypi/rp2xxx/src/spi_slave.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const std = @import("std");
const microzig = @import("microzig");

const rp2xxx = microzig.hal;
const time = rp2xxx.time;
const gpio = rp2xxx.gpio;
const chip = rp2xxx.compatibility.chip;

const BUF_LEN = 0x100;
const spi = rp2xxx.spi.instance.SPI0;

const uart = rp2xxx.uart.instance.num(0);
const uart_baud_rate = 115200;
const uart_tx_pin = gpio.num(0);

// These may change depending on which GPIO pins you have your SPI device routed to.
const CS_PIN = 17;
const SCK_PIN = 18;
// NOTE: rp2xxx doesn't label pins as MOSI/MISO. Instead a pin is always for
// either receiving or transmitting SPI data, no matter whether the chip is in
// master or slave mode.
const RX_PIN = 16;

pub const microzig_options = .{
.log_level = .debug,
.logFn = rp2xxx.uart.logFn,
};

pub fn main() !void {
// Set pin functions for CS, SCK, RX
const csn = gpio.num(CS_PIN);
const mosi = gpio.num(RX_PIN);
const sck = gpio.num(SCK_PIN);
inline for (&.{ csn, mosi, sck }) |pin| {
pin.set_function(.spi);
}

switch (chip) {
.RP2040 => uart_tx_pin.set_function(.uart),
.RP2350 => uart_tx_pin.set_function(.uart_first),
}
uart.apply(.{
.baud_rate = uart_baud_rate,
.clock_config = rp2xxx.clock_config,
});

rp2xxx.uart.init_logger(uart);

std.log.info("Setting SPI as slave device", .{});
spi.set_slave(true);

try spi.apply(.{ .clock_config = rp2xxx.clock_config });
var in_buf: [BUF_LEN]u8 = undefined;

std.log.info("Reading", .{});

while (true) {
spi.read_blocking(u8, 0, &in_buf);
std.log.info("Got: {s}", .{in_buf});
time.sleep_ms(1 * 1000);
}
}
14 changes: 12 additions & 2 deletions port/raspberrypi/rp2xxx/src/hal/spi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ const peripherals = microzig.chip.peripherals;
const SPI0_reg = peripherals.SPI0;
const SPI1_reg = peripherals.SPI1;

const gpio = @import("gpio.zig");
const clocks = @import("clocks.zig");
const resets = @import("resets.zig");
const time = @import("time.zig");
Expand Down Expand Up @@ -162,6 +161,17 @@ pub const SPI = enum(u1) {
spi_regs.SSPCPSR.modify(.{ .CPSDVSR = 0 });
}

pub fn set_slave(spi: SPI, slave: bool) void {
const regs = spi.get_regs();
// Disable SPI
regs.SSPCR1.modify(.{ .SSE = 0 });

regs.SSPCR1.modify(.{ .MS = @intFromBool(slave) });

// Re-enable SPI
regs.SSPCR1.modify(.{ .SSE = 1 });
}

pub inline fn is_writable(spi: SPI) bool {
return spi.get_regs().SSPSR.read().TNF == 1;
}
Expand Down Expand Up @@ -336,7 +346,7 @@ pub const SPI = enum(u1) {
/// be 0, but some devices require a specific value here,
/// e.g. SD cards expect 0xff
///
/// NOTE: This function is a vectored version of `write_blocking` and takes an array of arrays.
/// NOTE: This function is a vectored version of `read_blocking` and takes an array of arrays.
/// This pattern allows one to create better zero-copy send routines as message prefixes and
/// suffixes won't need to be concatenated/inserted to the original buffer, but can be managed
/// in a separate memory.
Expand Down

0 comments on commit 18cbbec

Please sign in to comment.