Moves microzig-examples to examples/

wch-ch32v003
Felix "xq" Queißner 9 months ago
commit 9a3b06aa31

@ -0,0 +1,38 @@
name: Build
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
dir:
- all-platforms
- raspberrypi-rp2040
- espressif-esp
- nxp-lpc
- microchip-atmega
- gigadevice-gd32
- nordic-nrf5x
- stmicro-stm32
os:
- windows-latest
- macos-latest
- ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Zig
uses: goto-bus-stop/setup-zig@v2
with:
version: 0.11.0
- name: Build examples
working-directory: ${{ matrix.dir }}
run: zig build

2
.gitignore vendored

@ -2,4 +2,4 @@ zig-out/
zig-cache/ zig-cache/
.DS_Store .DS_Store
.gdbinit .gdbinit
.lldbinit .lldbinit

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Zig Embedded Group
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,3 @@
# microzig-examples
Examples for embedded zig!

@ -0,0 +1,84 @@
const std = @import("std");
const rp2040 = @import("rp2040");
const stm32 = @import("stm32");
const lpc = @import("lpc");
const gd32 = @import("gd32");
const nrf5x = @import("nrf5x");
const esp = @import("esp");
const atmega = @import("atmega");
const available_targets = [_]TargetDesc{
// RP2040
.{ .name = "pico", .target = rp2040.boards.raspberry_pi.pico },
.{ .name = "rp2040-eth", .target = rp2040.boards.waveshare.rp2040_eth },
.{ .name = "rp2040-plus-4m", .target = rp2040.boards.waveshare.rp2040_plus_4m },
.{ .name = "rp2040-plus-16m", .target = rp2040.boards.waveshare.rp2040_plus_16m },
.{ .name = "rp2040-matrix", .target = rp2040.boards.waveshare.rp2040_matrix },
// STM32
.{ .name = "stm32f103x8", .target = stm32.chips.stm32f103x8 },
.{ .name = "stm32f303vc", .target = stm32.chips.stm32f303vc },
.{ .name = "stm32f407vg", .target = stm32.chips.stm32f407vg },
.{ .name = "stm32f429zit6u", .target = stm32.chips.stm32f429zit6u },
.{ .name = "stm32f3discovery", .target = stm32.boards.stm32f3discovery },
.{ .name = "stm32f4discovery", .target = stm32.boards.stm32f4discovery },
.{ .name = "stm3240geval", .target = stm32.boards.stm3240geval },
.{ .name = "stm32f429idiscovery", .target = stm32.boards.stm32f429idiscovery },
// NXP LPC
.{ .name = "lpc176x5x", .target = lpc.chips.lpc176x5x },
.{ .name = "mbed-lpc1768", .target = lpc.boards.mbed.lpc1768 },
// GigaDevice GD32
.{ .name = "gd32vf103xb", .target = gd32.chips.gd32vf103xb },
.{ .name = "gd32vf103x8", .target = gd32.chips.gd32vf103x8 },
.{ .name = "sipeed-longan_nano", .target = gd32.boards.sipeed.longan_nano },
// Nordic Nrf5x
.{ .name = "nrf52832", .target = nrf5x.chips.nrf52832 },
.{ .name = "nrf52840", .target = nrf5x.chips.nrf52840 },
.{ .name = "nrf52840-dongle", .target = nrf5x.boards.nordic.nRF52840_Dongle }, // TODO: Add support for DFU files!
// RISC-V Espressif ESP
.{ .name = "esp32-c3", .target = esp.chips.esp32_c3 }, // TODO: Add support for Espressif Update Binaries
// Microchip ATmega
// TODO: Fix compiler bugs
// - https://github.com/ziglang/zig/issues/17219
// .{ .name = "atmega328p", .target = atmega.chips.atmega328p },
// .{ .name = "arduino-nano", .target = atmega.boards.arduino.nano },
// .{ .name = "arduino-uno-rev3", .target = atmega.boards.arduino.uno_rev3 },
};
pub fn build(b: *std.Build) void {
const microzig = @import("microzig").init(b, "microzig");
const optimize = b.standardOptimizeOption(.{});
for (available_targets) |dest| {
// `addFirmware` basically works like addExecutable, but takes a
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
//
// The target will convey all necessary information on the chip,
// cpu and potentially the board as well.
const firmware = microzig.addFirmware(b, .{
.name = b.fmt("empty-{s}", .{dest.name}),
.target = dest.target,
.optimize = optimize,
.source_file = .{ .path = "src/empty.zig" },
});
// `installFirmware()` is the MicroZig pendant to `Build.installArtifact()`
// and allows installing the firmware as a typical firmware file.
//
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
microzig.installFirmware(b, firmware, .{});
// For debugging, we also always install the firmware as an ELF file
microzig.installFirmware(b, firmware, .{ .format = .elf });
}
}
const TargetDesc = struct {
target: @import("microzig").Target,
name: []const u8,
};

@ -0,0 +1,38 @@
.{
.name = "microzig-all-platforms-examples",
.version = "0.1.0",
.dependencies = .{
.microzig = .{
.url = "https://github.com/ZigEmbeddedGroup/microzig/archive/c6c9ec4516f57638e751141085c9d76120990312.tar.gz",
.hash = "1220af58bdaa721b8189f3a7adfda660517dd354463463388e96d69fe4ceccf80b92",
},
.rp2040 = .{
.url = "https://github.com/ZigEmbeddedGroup/raspberrypi-rp2040/archive/67d36eebb0fbd89633db1a51d6d2bcb049f2066a.tar.gz",
.hash = "122094bf268f45b188f3916f9e5964f4257414afaafba98a455ac47d25389a456832",
},
.stm32 = .{
.url = "https://github.com/ZigEmbeddedGroup/stmicro-stm32/archive/cb2893707efa6aa289fa72f02959ad5f2d9db2a1.tar.gz",
.hash = "12208cab5f60ef97cac4165ad694f3ba0c7b28f279538c1539b74f7c152f34fe306d",
},
.lpc = .{
.url = "https://github.com/ZigEmbeddedGroup/nxp-lpc/archive/130a1316c0892415e7da958a5e9548ed87bba54d.tar.gz",
.hash = "1220165879f85a1d51656d35b3963a95f3585dc665fc7414f76aa6aad4e6635536cf",
},
.gd32 = .{
.url = "https://github.com/ZigEmbeddedGroup/gigadevice-gd32/archive/9324753cc3b8e7afe83fcda085bcfe76681a3be3.tar.gz",
.hash = "122043ff4dcbc342f25dbb936b0d9eaa701ac3509e2cbe6764be37b90d31c7a385d0",
},
.nrf5x = .{
.url = "https://github.com/ZigEmbeddedGroup/nordic-nrf5x/archive/0ab136860ccf7eb1d07969c3ef523f3cd898e2ff.tar.gz",
.hash = "1220980da06f9634dcff06afefa7aa111bd030018fea49f79e86657dab69621e1d08",
},
.esp = .{
.url = "https://github.com/ZigEmbeddedGroup/espressif-esp/archive/59b8ca028915c0d6224ec88dbf4db19afbb559c0.tar.gz",
.hash = "1220f6e5f22416fdc63442cd8869fcaa35f9abf30d878ea3d80073176677dc6f8a65",
},
.atmega = .{
.url = "https://github.com/ZigEmbeddedGroup/microchip-atmega/archive/feefcb87a63c0aae31afb783d4e388e90c4d922f.tar.gz",
.hash = "1220048dc5d22729ee119a496f8b8ca3556838af1f3bd32ce6acd5f76480ec942965",
},
},
}

@ -0,0 +1,20 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const time = rp2040.time;
const pin_config = rp2040.pins.GlobalConfiguration{
.GPIO25 = .{
.name = "led",
.direction = .out,
},
};
pub fn main() !void {
const pins = pin_config.apply();
while (true) {
pins.led.toggle();
time.sleep_ms(250);
}
}

@ -0,0 +1,6 @@
const std = @import("std");
const microzig = @import("microzig");
pub fn main() void {
//
}

@ -0,0 +1,4 @@
# Examples for the BSP `espressif-esp`
- [Blinky](src/blinky.zig) on [ESP32-C3-32S-Kit](https://www.waveshare.com/wiki/ESP-C3-32S-Kit)
Showcases how to do a simple RGB cycling.

@ -0,0 +1,45 @@
const std = @import("std");
const esp = @import("esp");
const available_targets = [_]TargetDesc{
.{ .name = "esp32-c3", .target = esp.chips.esp32_c3 },
};
const available_examples = [_][]const u8{
"src/blinky.zig",
};
pub fn build(b: *std.Build) void {
const microzig = @import("microzig").init(b, "microzig");
const optimize = b.standardOptimizeOption(.{});
for (available_targets) |target| {
for (available_examples) |example| {
// `addFirmware` basically works like addExecutable, but takes a
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
//
// The target will convey all necessary information on the chip,
// cpu and potentially the board as well.
const firmware = microzig.addFirmware(b, .{
.name = b.fmt("{s}-{s}", .{ std.fs.path.stem(example), target.name }),
.target = target.target,
.optimize = optimize,
.source_file = .{ .path = example },
});
// `installFirmware()` is the MicroZig pendant to `Build.installArtifact()`
// and allows installing the firmware as a typical firmware file.
//
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
microzig.installFirmware(b, firmware, .{});
// For debugging, we also always install the firmware as an ELF file
microzig.installFirmware(b, firmware, .{ .format = .elf });
}
}
}
const TargetDesc = struct {
target: @import("microzig").Target,
name: []const u8,
};

@ -0,0 +1,14 @@
.{
.name = "microzig-espressif-esp-examples",
.version = "0.1.0",
.dependencies = .{
.microzig = .{
.url = "https://github.com/ZigEmbeddedGroup/microzig/archive/c6c9ec4516f57638e751141085c9d76120990312.tar.gz",
.hash = "1220af58bdaa721b8189f3a7adfda660517dd354463463388e96d69fe4ceccf80b92",
},
.esp = .{
.url = "https://github.com/ZigEmbeddedGroup/espressif-esp/archive/59b8ca028915c0d6224ec88dbf4db19afbb559c0.tar.gz",
.hash = "1220f6e5f22416fdc63442cd8869fcaa35f9abf30d878ea3d80073176677dc6f8a65",
},
},
}

@ -0,0 +1,90 @@
const std = @import("std");
const microzig = @import("microzig");
const peripherals = microzig.chip.peripherals;
const TIMG0 = peripherals.TIMG0;
const RTC_CNTL = peripherals.RTC_CNTL;
const INTERRUPT_CORE0 = peripherals.INTERRUPT_CORE0;
const GPIO = peripherals.GPIO;
const IO_MUX = peripherals.IO_MUX;
const dogfood: u32 = 0x50D83AA1;
const super_dogfood: u32 = 0x8F1D312A;
const LED_R_PIN = 3; // GPIO
const LED_G_PIN = 4; // GPIO
const LED_B_PIN = 5; // GPIO
const led_pins = [_]u32{
LED_R_PIN,
LED_G_PIN,
LED_B_PIN,
};
pub fn main() !void {
// Feed and disable watchdog 0
TIMG0.WDTWPROTECT.raw = dogfood;
TIMG0.WDTCONFIG0.raw = 0;
TIMG0.WDTWPROTECT.raw = 0;
// Feed and disable rtc watchdog
RTC_CNTL.WDTWPROTECT.raw = dogfood;
RTC_CNTL.WDTCONFIG0.raw = 0;
RTC_CNTL.WDTWPROTECT.raw = 0;
// Feed and disable rtc super watchdog
RTC_CNTL.SWD_WPROTECT.raw = super_dogfood;
RTC_CNTL.SWD_CONF.modify(.{ .SWD_DISABLE = 1 });
RTC_CNTL.SWD_WPROTECT.raw = 0;
// Disable all interrupts
INTERRUPT_CORE0.CPU_INT_ENABLE.raw = 0;
GPIO.ENABLE.modify(.{
.DATA = (1 << LED_R_PIN) |
(1 << LED_G_PIN) |
(1 << LED_B_PIN),
});
for (led_pins) |pin| {
IO_MUX.GPIO[pin].modify(.{
.MCU_OE = 1, // 1: output enabled
.SLP_SEL = 0, // Set to 1 to put the pin in sleep mode. (R/W)
.MCU_WPD = 0, // 0: internal pull-down disabled. (R/W)
.MCU_WPU = 0, // 0: internal pull-up disabled. (R/W)
.MCU_IE = 0, // 0: input disabled. (R/W)
.FUN_WPD = 0, // 0: internal pull-down disabled. (R/W)
.FUN_WPU = 0, // 0: internal pull-up disabled. (R/W)
.FUN_IE = 0, // 0: input disabled. (R/W)
.FUN_DRV = 3, // Select the drive strength of the pin. 0: ~5 mA; 1: ~ 10 mA; 2: ~ 20 mA; 3: ~40mA. (R/W)
.MCU_SEL = 1, // 1: GPIO
.FILTER_EN = 0, // 0: Filter disabled. (R/W)
});
GPIO.FUNC_OUT_SEL_CFG[pin].write(.{
// If a value 128 is written to this field, bit n of GPIO_OUT_REG and GPIO_ENABLE_REG will be selected as the output value and output enable. (R/W)
.OUT_SEL = 0x80,
.INV_SEL = 0x00, // 0: Do not invert the output value
.OEN_SEL = 0x01, // 1: Force the output enable signal to be sourced from bit n of GPIO_ENABLE_REG. (R/W)
.OEN_INV_SEL = 0x00, // 0: Do not invert the output enable signal
.padding = 0,
});
}
microzig.hal.uart.write(0, "Hello from Zig!\r\n");
while (true) {
GPIO.OUT.modify(.{ .DATA_ORIG = (1 << LED_R_PIN) });
microzig.hal.uart.write(0, "R");
microzig.core.experimental.debug.busy_sleep(100_000);
GPIO.OUT.modify(.{ .DATA_ORIG = (1 << LED_G_PIN) });
microzig.hal.uart.write(0, "G");
microzig.core.experimental.debug.busy_sleep(100_000);
GPIO.OUT.modify(.{ .DATA_ORIG = (1 << LED_B_PIN) });
microzig.hal.uart.write(0, "B");
microzig.core.experimental.debug.busy_sleep(100_000);
}
}

@ -0,0 +1,42 @@
const std = @import("std");
const gd32 = @import("gd32");
const available_examples = [_]Example{
// .{ .name = "gd32vf103xb", .target = gd32.chips.gd32vf103xb, .file = "src/blinky.zig" },
// .{ .name = "gd32vf103x8", .target = gd32.chips.gd32vf103x8, .file = "src/blinky.zig" },
// .{ .name = "sipeed-longan_nano", .target = gd32.boards.sipeed.longan_nano, .file = "src/blinky.zig" },
};
pub fn build(b: *std.Build) void {
const microzig = @import("microzig").init(b, "microzig");
const optimize = .ReleaseSmall; // The others are not really an option on AVR
for (available_examples) |example| {
// `addFirmware` basically works like addExecutable, but takes a
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
//
// The target will convey all necessary information on the chip,
// cpu and potentially the board as well.
const firmware = microzig.addFirmware(b, .{
.name = example.name,
.target = example.target,
.optimize = optimize,
.source_file = .{ .path = example.file },
});
// `installFirmware()` is the MicroZig pendant to `Build.installArtifact()`
// and allows installing the firmware as a typical firmware file.
//
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
microzig.installFirmware(b, firmware, .{});
// For debugging, we also always install the firmware as an ELF file
microzig.installFirmware(b, firmware, .{ .format = .elf });
}
}
const Example = struct {
target: @import("microzig").Target,
name: []const u8,
file: []const u8,
};

@ -0,0 +1,14 @@
.{
.name = "microzig-gigadevice-gd32-examples",
.version = "0.1.0",
.dependencies = .{
.microzig = .{
.url = "https://github.com/ZigEmbeddedGroup/microzig/archive/c6c9ec4516f57638e751141085c9d76120990312.tar.gz",
.hash = "1220af58bdaa721b8189f3a7adfda660517dd354463463388e96d69fe4ceccf80b92",
},
.gd32 = .{
.url = "https://github.com/ZigEmbeddedGroup/gigadevice-gd32/archive/9324753cc3b8e7afe83fcda085bcfe76681a3be3.tar.gz",
.hash = "122043ff4dcbc342f25dbb936b0d9eaa701ac3509e2cbe6764be37b90d31c7a385d0",
},
},
}

@ -0,0 +1,40 @@
const std = @import("std");
const atmega = @import("atmega");
const available_examples = [_]Example{
// TODO: .{ .name = "arduino-nano_blinky", .target = atmega.boards.arduino.nano, .file = "src/blinky.zig" },
};
pub fn build(b: *std.Build) void {
const microzig = @import("microzig").init(b, "microzig");
const optimize = .ReleaseSmall; // The others are not really an option on AVR
for (available_examples) |example| {
// `addFirmware` basically works like addExecutable, but takes a
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
//
// The target will convey all necessary information on the chip,
// cpu and potentially the board as well.
const firmware = microzig.addFirmware(b, .{
.name = example.name,
.target = example.target,
.optimize = optimize,
.source_file = .{ .path = example.file },
});
// `installFirmware()` is the MicroZig pendant to `Build.installArtifact()`
// and allows installing the firmware as a typical firmware file.
//
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
microzig.installFirmware(b, firmware, .{});
// For debugging, we also always install the firmware as an ELF file
microzig.installFirmware(b, firmware, .{ .format = .elf });
}
}
const Example = struct {
target: @import("microzig").Target,
name: []const u8,
file: []const u8,
};

@ -0,0 +1,14 @@
.{
.name = "microzig-microchip-atmega-examples",
.version = "0.1.0",
.dependencies = .{
.microzig = .{
.url = "https://github.com/ZigEmbeddedGroup/microzig/archive/c6c9ec4516f57638e751141085c9d76120990312.tar.gz",
.hash = "1220af58bdaa721b8189f3a7adfda660517dd354463463388e96d69fe4ceccf80b92",
},
.atmega = .{
.url = "https://github.com/ZigEmbeddedGroup/microchip-atmega/archive/feefcb87a63c0aae31afb783d4e388e90c4d922f.tar.gz",
.hash = "1220048dc5d22729ee119a496f8b8ca3556838af1f3bd32ce6acd5f76480ec942965",
},
},
}

@ -0,0 +1,15 @@
const std = @import("std");
const microzig = @import("microzig");
// LED is PB5
const port = microzig.chip.peripherals.PORTB;
pub fn main() void {
port.DDRB |= (1 << 5);
port.PORTB |= 0x00;
while (true) {
microzig.core.experimental.debug.busy_sleep(1_000);
port.PINB |= (1 << 5);
}
}

@ -0,0 +1,11 @@
= Nordic nrf5x
HALs and register definitions for nrf5x devices
== What version of Zig to use
Right now we are following https://ziglang.org/download/[master], but once 0.11.0 is released, we will be switching to the latest stable version of Zig.
== Renode supports:
- nrf52840 development kit

@ -0,0 +1,40 @@
const std = @import("std");
const nrf5x = @import("nrf5x");
const available_examples = [_]Example{
.{ .name = "nrf52480-dongle_blinky", .target = nrf5x.boards.nordic.nRF52840_Dongle, .file = "src/blinky.zig" },
};
pub fn build(b: *std.Build) void {
const microzig = @import("microzig").init(b, "microzig");
const optimize = b.standardOptimizeOption(.{});
for (available_examples) |example| {
// `addFirmware` basically works like addExecutable, but takes a
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
//
// The target will convey all necessary information on the chip,
// cpu and potentially the board as well.
const firmware = microzig.addFirmware(b, .{
.name = example.name,
.target = example.target,
.optimize = optimize,
.source_file = .{ .path = example.file },
});
// `installFirmware()` is the MicroZig pendant to `Build.installArtifact()`
// and allows installing the firmware as a typical firmware file.
//
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
microzig.installFirmware(b, firmware, .{});
// For debugging, we also always install the firmware as an ELF file
microzig.installFirmware(b, firmware, .{ .format = .elf });
}
}
const Example = struct {
target: @import("microzig").Target,
name: []const u8,
file: []const u8,
};

@ -0,0 +1,14 @@
.{
.name = "microzig-nordic-nrf5x-examples",
.version = "0.1.0",
.dependencies = .{
.microzig = .{
.url = "https://github.com/ZigEmbeddedGroup/microzig/archive/c6c9ec4516f57638e751141085c9d76120990312.tar.gz",
.hash = "1220af58bdaa721b8189f3a7adfda660517dd354463463388e96d69fe4ceccf80b92",
},
.nrf5x = .{
.url = "https://github.com/ZigEmbeddedGroup/nordic-nrf5x/archive/0ab136860ccf7eb1d07969c3ef523f3cd898e2ff.tar.gz",
.hash = "1220980da06f9634dcff06afefa7aa111bd030018fea49f79e86657dab69621e1d08",
},
},
}

@ -0,0 +1,6 @@
const std = @import("std");
const microzig = @import("microzig");
pub fn main() !void {
// TODO: Implement the blinky
}

@ -0,0 +1,5 @@
# Examples for the BSP `nxp-lpc`
- [Blinky](src/blinky.zig) on [nRF52840 Dongle](https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle)
TODO: Implement this!

@ -0,0 +1,40 @@
const std = @import("std");
const lpc = @import("lpc");
const available_examples = [_]ExampleDesc{
.{ .name = "mbed-lpc1768_blinky", .target = lpc.boards.mbed.lpc1768, .file = "src/blinky.zig" },
};
pub fn build(b: *std.Build) void {
const microzig = @import("microzig").init(b, "microzig");
const optimize = b.standardOptimizeOption(.{});
for (available_examples) |example| {
// `addFirmware` basically works like addExecutable, but takes a
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
//
// The target will convey all necessary information on the chip,
// cpu and potentially the board as well.
const firmware = microzig.addFirmware(b, .{
.name = example.name,
.target = example.target,
.optimize = optimize,
.source_file = .{ .path = example.file },
});
// `installFirmware()` is the MicroZig pendant to `Build.installArtifact()`
// and allows installing the firmware as a typical firmware file.
//
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
microzig.installFirmware(b, firmware, .{});
// For debugging, we also always install the firmware as an ELF file
microzig.installFirmware(b, firmware, .{ .format = .elf });
}
}
const ExampleDesc = struct {
target: @import("microzig").Target,
name: []const u8,
file: []const u8,
};

@ -0,0 +1,14 @@
.{
.name = "microzig-nxp-lpc-examples",
.version = "0.1.0",
.dependencies = .{
.microzig = .{
.url = "https://github.com/ZigEmbeddedGroup/microzig/archive/c6c9ec4516f57638e751141085c9d76120990312.tar.gz",
.hash = "1220af58bdaa721b8189f3a7adfda660517dd354463463388e96d69fe4ceccf80b92",
},
.lpc = .{
.url = "https://github.com/ZigEmbeddedGroup/nxp-lpc/archive/130a1316c0892415e7da958a5e9548ed87bba54d.tar.gz",
.hash = "1220165879f85a1d51656d35b3963a95f3585dc665fc7414f76aa6aad4e6635536cf",
},
},
}

@ -0,0 +1,56 @@
const std = @import("std");
const microzig = @import("microzig");
const chip = microzig.chip;
// LED-1: P1.18
// LED-2: P1.20
// LED-3: P1.21
// LED-4: P1.23
const conn = chip.peripherals.PINCONNECT;
const gpio: *volatile [5]PatchedGpio = @ptrCast(@alignCast(chip.peripherals.GPIO));
const led_mask = [4]u32{
(1 << 18),
(1 << 20),
(1 << 21),
(1 << 23),
};
const all_mask = led_mask[0] | led_mask[1] | led_mask[2] | led_mask[3];
pub fn main() !void {
conn.PINSEL3.modify(.{
.P1_18 = .{ .value = .GPIO_P1 },
.P1_20 = .{ .value = .GPIO_P1 },
.P1_21 = .{ .value = .GPIO_P1 },
.P1_23 = .{ .value = .GPIO_P1 },
});
const p1 = &gpio[1];
p1.dir = all_mask;
while (true) {
for (led_mask) |mask| {
p1.pin_clr = (all_mask & ~mask);
p1.pin_set = mask;
microzig.core.experimental.debug.busy_sleep(100_000);
}
}
}
const PatchedGpio = extern struct {
dir: u32, // 0x2009 C000
__padding0: u32, // 0x2009 C004
__padding1: u32, // 0x2009 C008
__padding2: u32, // 0x2009 C00C
mask: u32, // 0x2009 C010
pin: u32, // 0x2009 C014
pin_set: u32, // 0x2009 C018
pin_clr: u32, // 0x2009 C01C
comptime {
std.debug.assert(@sizeOf(PatchedGpio) == 0x20);
}
};

@ -0,0 +1,50 @@
# Examples for the BSP `raspberrypi-rp2040`
## Demos
All demos that run on the [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) can also be run on the [RP2040-Plus](https://www.waveshare.com/rp2040-plus.htm) without modification.
- [adc](src/adc.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
This example takes periodic samples of the temperature sensor and prints it to the UART using the stdlib logging facility.
- [blinky](src/blinky.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Blinks the LED on the board.
- [blinky core1](src/blinky_core1.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Blinks the LED on the board using the second CPU.
- [flash program](src/flash_program.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Writes and reads data into the flash.
- [gpio clk](src/gpio_clk.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Enables a `CLKOUT` mode on GPIO0.
- [i2c bus scan](src/i2c_bus_scan.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Prints all I²C devices on UART0 (Pin 0,1) attached to I²C on SCL=GPIO4, SDA=GPIO5.
- [pwm](src/pwm.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Slowly blinks the LED on the Pico with a smooth blinking using PWM.
- [random](src/random.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Showcases how to use the internal random generator.
- [spi master](src/spi_master.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Showcases how to use the SPI host controller.
- [squarewave](src/squarewave.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Showcases how to use the PIO to emit a basic square wave.
- [uart](src/uart.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Showcases how to use the UART together with `std.log`.
- [usb device](src/usb_device.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
A really basic example for a raw USB device. You can use the Python 3 script [`scripts/usb_device_loopback.py`](scripts/usb_device_loopback.py) to test the USB device.
- [usb hid](src/usb_hid.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
A really basic example how to implement a USB HID device. You can use the Python 3 script [`scripts/hid_test.py`](scripts/hid_test.py) to test the HID device.
- [ws2812](src/ws2812.zig) on [RaspberryPi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/)
Showcases how to control one WS2812 LED attached to GPIO23.
- [tiles](src/tiles.zig) on [RP2040-Matrix](https://www.waveshare.com/rp2040-matrix.htm)
Showcases how to control the LED matrix on the development board to do a simple color flipper effect.
## Flashing
You can flash all examples using either your file browser by dragging the example `.uf2` file from `zig-out/firmware/` to the directory.
Or you can use [`picotool`](https://github.com/raspberrypi/picotool) to flash a uf2 file:
```sh-session
[user@host] raspberrypi-rp2040/ $ picotool load -x zig-out/firmware/${file}.uf2
Loading into Flash: [==============================] 100%
The device was rebooted to start the application.
[user@host] raspberrypi-rp2040/ $
```

@ -0,0 +1,59 @@
const std = @import("std");
const rp2040 = @import("rp2040");
const available_examples = [_]Example{
.{ .name = "pico_adc", .target = rp2040.boards.raspberry_pi.pico, .file = "src/adc.zig" },
.{ .name = "pico_blinky", .target = rp2040.boards.raspberry_pi.pico, .file = "src/blinky.zig" },
// TODO: Fix multicore hal! .{ .name = "pico", .target = rp2040.boards.raspberry_pi.pico , .file = "src/blinky_core1.zig" },
.{ .name = "pico_flash-program", .target = rp2040.boards.raspberry_pi.pico, .file = "src/flash_program.zig" },
.{ .name = "pico_gpio-clk", .target = rp2040.boards.raspberry_pi.pico, .file = "src/gpio_clk.zig" },
.{ .name = "pico_i2c-bus-scan", .target = rp2040.boards.raspberry_pi.pico, .file = "src/i2c_bus_scan.zig" },
.{ .name = "pico_pwm", .target = rp2040.boards.raspberry_pi.pico, .file = "src/pwm.zig" },
.{ .name = "pico_random", .target = rp2040.boards.raspberry_pi.pico, .file = "src/random.zig" },
.{ .name = "pico_spi-master", .target = rp2040.boards.raspberry_pi.pico, .file = "src/spi_master.zig" },
.{ .name = "pico_squarewave", .target = rp2040.boards.raspberry_pi.pico, .file = "src/squarewave.zig" },
.{ .name = "pico_uart", .target = rp2040.boards.raspberry_pi.pico, .file = "src/uart.zig" },
.{ .name = "pico_usb-device", .target = rp2040.boards.raspberry_pi.pico, .file = "src/usb_device.zig" },
.{ .name = "pico_usb-hid", .target = rp2040.boards.raspberry_pi.pico, .file = "src/usb_hid.zig" },
.{ .name = "pico_ws2812", .target = rp2040.boards.raspberry_pi.pico, .file = "src/ws2812.zig" },
.{ .name = "rp2040-matrix_tiles", .target = rp2040.boards.waveshare.rp2040_matrix, .file = "src/tiles.zig" },
// .{ .name = "rp2040-eth", .target = rp2040.boards.waveshare.rp2040_eth },
// .{ .name = "rp2040-plus-4m", .target = rp2040.boards.waveshare.rp2040_plus_4m },
// .{ .name = "rp2040-plus-16m", .target = rp2040.boards.waveshare.rp2040_plus_16m },
};
pub fn build(b: *std.Build) void {
const microzig = @import("microzig").init(b, "microzig");
const optimize = b.standardOptimizeOption(.{});
for (available_examples) |example| {
// `addFirmware` basically works like addExecutable, but takes a
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
//
// The target will convey all necessary information on the chip,
// cpu and potentially the board as well.
const firmware = microzig.addFirmware(b, .{
.name = example.name,
.target = example.target,
.optimize = optimize,
.source_file = .{ .path = example.file },
});
// `installFirmware()` is the MicroZig pendant to `Build.installArtifact()`
// and allows installing the firmware as a typical firmware file.
//
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
microzig.installFirmware(b, firmware, .{});
// For debugging, we also always install the firmware as an ELF file
microzig.installFirmware(b, firmware, .{ .format = .elf });
}
}
const Example = struct {
target: @import("microzig").Target,
name: []const u8,
file: []const u8,
};

@ -0,0 +1,14 @@
.{
.name = "microzig-raspberrypi-rp2040-examples",
.version = "0.1.0",
.dependencies = .{
.microzig = .{
.url = "https://github.com/ZigEmbeddedGroup/microzig/archive/c6c9ec4516f57638e751141085c9d76120990312.tar.gz",
.hash = "1220af58bdaa721b8189f3a7adfda660517dd354463463388e96d69fe4ceccf80b92",
},
.rp2040 = .{
.url = "https://github.com/ZigEmbeddedGroup/raspberrypi-rp2040/archive/67d36eebb0fbd89633db1a51d6d2bcb049f2066a.tar.gz",
.hash = "122094bf268f45b188f3916f9e5964f4257414afaafba98a455ac47d25389a456832",
},
},
}

@ -0,0 +1,29 @@
#!/usr/bin/env python3
# Install python3 HID package https://pypi.org/project/hid/
import hid
# default is TinyUSB (0xcafe), Adafruit (0x239a), RaspberryPi (0x2e8a), Espressif (0x303a) VID
USB_VID = (0xcafe, 0x239a, 0x2e8a, 0x303a)
print("VID list: " + ", ".join('%02x' % v for v in USB_VID))
for vid in USB_VID:
for dict in hid.enumerate(vid):
print(dict)
dev = hid.Device(dict['vendor_id'], dict['product_id'])
if dev:
while True:
inp = input("Send text to HID Device : ").encode('utf-8')
dev.write(inp)
x = 0
l = len(inp)
r = b""
while (x < l):
str_in = dev.read(64)
r += str_in
x += 64
print("Received from HID Device:\n", r)
print("hex:\n", r.hex())

@ -0,0 +1,48 @@
#!/usr/bin/env python3
#
# Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# sudo pip3 install pyusb
import usb.core
import usb.util
# find our device
dev = usb.core.find(idVendor=0x0000, idProduct=0x0001)
# was it found?
if dev is None:
raise ValueError('Device not found')
# get an endpoint instance
cfg = dev.get_active_configuration()
intf = cfg[(0, 0)]
outep = usb.util.find_descriptor(
intf,
# match the first OUT endpoint
custom_match= \
lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_OUT)
inep = usb.util.find_descriptor(
intf,
# match the first IN endpoint
custom_match= \
lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_IN)
assert inep is not None
assert outep is not None
test_string = "Hello World!"
outep.write(test_string)
from_device = inep.read(len(test_string))
print("Device Says: {}".format(''.join([chr(x) for x in from_device])))

@ -0,0 +1,40 @@
//! This example takes periodic samples of the temperature sensor and
//! prints it to the UART using the stdlib logging facility.
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const gpio = rp2040.gpio;
const adc = rp2040.adc;
const time = rp2040.time;
const uart = rp2040.uart.num(0);
const baud_rate = 115200;
const uart_tx_pin = gpio.num(0);
const uart_rx_pin = gpio.num(1);
pub const std_options = struct {
pub const logFn = rp2040.uart.log;
};
pub fn main() void {
adc.apply(.{
.temp_sensor_enabled = true,
});
uart.apply(.{
.baud_rate = baud_rate,
.tx_pin = uart_tx_pin,
.rx_pin = uart_rx_pin,
.clock_config = rp2040.clock_config,
});
rp2040.uart.init_logger(uart);
while (true) : (time.sleep_ms(1000)) {
const sample = adc.convert_one_shot_blocking(.temp_sensor) catch {
std.log.err("conversion failed!", .{});
continue;
};
std.log.info("temp value: {}", .{sample});
}
}

@ -0,0 +1,20 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const time = rp2040.time;
const pin_config = rp2040.pins.GlobalConfiguration{
.GPIO25 = .{
.name = "led",
.direction = .out,
},
};
pub fn main() !void {
const pins = pin_config.apply();
while (true) {
pins.led.toggle();
time.sleep_ms(250);
}
}

@ -0,0 +1,28 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const gpio = rp2040.gpio;
const time = rp2040.time;
const multicore = rp2040.multicore;
const led = gpio.num(25);
fn core1() void {
while (true) {
led.put(1);
time.sleep_ms(250);
led.put(0);
time.sleep_ms(250);
}
}
pub fn main() !void {
led.set_function(.sio);
led.set_direction(.out);
multicore.launch_core1(core1);
while (true) {
microzig.cpu.wfi();
}
}

@ -0,0 +1,81 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const flash = rp2040.flash;
const time = rp2040.time;
const gpio = rp2040.gpio;
const clocks = rp2040.clocks;
const led = gpio.num(25);
const uart = rp2040.uart.num(0);
const baud_rate = 115200;
const uart_tx_pin = gpio.num(0);
const uart_rx_pin = gpio.num(1);
const flash_target_offset: u32 = 256 * 1024;
const flash_target_contents = @as([*]const u8, @ptrFromInt(rp2040.flash.XIP_BASE + flash_target_offset));
pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
std.log.err("panic: {s}", .{message});
@breakpoint();
while (true) {}
}
pub const std_options = struct {
pub const log_level = .debug;
pub const logFn = rp2040.uart.log;
};
pub fn main() !void {
led.set_function(.sio);
led.set_direction(.out);
led.put(1);
uart.apply(.{
.baud_rate = baud_rate,
.tx_pin = uart_tx_pin,
.rx_pin = uart_rx_pin,
.clock_config = rp2040.clock_config,
});
rp2040.uart.init_logger(uart);
var data: [flash.PAGE_SIZE]u8 = undefined;
var i: usize = 0;
var j: u8 = 0;
while (i < flash.PAGE_SIZE) : (i += 1) {
data[i] = j;
if (j == 255) j = 0;
j += 1;
}
std.log.info("Generate data", .{});
std.log.info("data: {s}", .{&data});
// Note that a whole number of sectors (4096 bytes) must be erased at a time
std.log.info("Erasing target region...", .{});
flash.range_erase(flash_target_offset, flash.SECTOR_SIZE);
std.log.info("Done. Read back target region:", .{});
std.log.info("data: {s}", .{flash_target_contents[0..flash.PAGE_SIZE]});
// Note that a whole number of pages (256 bytes) must be written at a time
std.log.info("Programming target region...", .{});
flash.range_program(flash_target_offset, data[0..]);
std.log.info("Done. Read back target region:", .{});
std.log.info("data: {s}", .{flash_target_contents[0..flash.PAGE_SIZE]});
var mismatch: bool = false;
i = 0;
while (i < flash.PAGE_SIZE) : (i += 1) {
if (data[i] != flash_target_contents[i])
mismatch = true;
}
if (mismatch) {
std.log.info("Programming failed!", .{});
} else {
std.log.info("Programming successful!", .{});
}
}

@ -0,0 +1,16 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const gpio = rp2040.gpio;
const clocks = rp2040.clocks;
const gpout0_pin = gpio.num(21);
const clock_config = clocks.GlobalConfiguration.init(.{
.sys = .{ .source = .src_xosc },
.gpout0 = .{ .source = .clk_sys },
});
pub fn main() !void {
gpout0_pin.set_function(.gpck);
while (true) {}
}

@ -0,0 +1,44 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const i2c = rp2040.i2c;
const gpio = rp2040.gpio;
const peripherals = microzig.chip.peripherals;
pub const std_options = struct {
pub const log_level = .info;
pub const logFn = rp2040.uart.log;
};
const uart = rp2040.uart.num(0);
const i2c0 = i2c.num(0);
pub fn main() !void {
uart.apply(.{
.baud_rate = 115200,
.tx_pin = gpio.num(0),
.rx_pin = gpio.num(1),
.clock_config = rp2040.clock_config,
});
rp2040.uart.init_logger(uart);
_ = i2c0.apply(.{
.clock_config = rp2040.clock_config,
.scl_pin = gpio.num(4),
.sda_pin = gpio.num(5),
});
for (0..std.math.maxInt(u7)) |addr| {
const a: i2c.Address = @enumFromInt(addr);
// Skip over any reserved addresses.
if (a.is_reserved()) continue;
var rx_data: [1]u8 = undefined;
_ = i2c0.read_blocking(a, &rx_data) catch continue;
std.log.info("I2C device found at address {X}.", .{addr});
}
}

@ -0,0 +1,29 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const gpio = rp2040.gpio;
const clocks = rp2040.clocks;
const time = rp2040.time;
const regs = microzig.chip.registers;
const multicore = rp2040.multicore;
const pin_config = rp2040.pins.GlobalConfiguration{
.GPIO25 = .{ .name = "led", .function = .PWM4_B },
};
pub fn main() !void {
const pins = pin_config.apply();
pins.led.slice().set_wrap(100);
pins.led.slice().enable();
while (true) {
for (0..101) |level| {
pins.led.set_level(@truncate(level));
time.sleep_ms(10);
}
for (1..100) |level| {
pins.led.set_level(@truncate(100 - level));
time.sleep_ms(10);
}
}
}

@ -0,0 +1,68 @@
//! Example that generates a 4 byte random number every second and outputs the result over UART
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const flash = rp2040.flash;
const time = rp2040.time;
const gpio = rp2040.gpio;
const clocks = rp2040.clocks;
const rand = rp2040.rand;
const led = gpio.num(25);
const uart = rp2040.uart.num(0);
const baud_rate = 115200;
const uart_tx_pin = gpio.num(0);
const uart_rx_pin = gpio.num(1);
pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
std.log.err("panic: {s}", .{message});
@breakpoint();
while (true) {}
}
pub const std_options = struct {
pub const log_level = .debug;
pub const logFn = rp2040.uart.log;
};
pub fn main() !void {
led.set_function(.sio);
led.set_direction(.out);
led.put(1);
uart.apply(.{
.baud_rate = baud_rate,
.tx_pin = uart_tx_pin,
.rx_pin = uart_rx_pin,
.clock_config = rp2040.clock_config,
});
var ascon = rand.Ascon.init();
var rng = ascon.random();
rp2040.uart.init_logger(uart);
var buffer: [8]u8 = undefined;
var dist: [256]usize = .{0} ** 256;
var counter: usize = 0;
while (true) {
rng.bytes(buffer[0..]);
counter += 8;
for (buffer) |byte| {
dist[@as(usize, @intCast(byte))] += 1;
}
std.log.info("Generate random number: {any}", .{buffer});
if (counter % 256 == 0) {
var i: usize = 0;
std.log.info("Distribution:", .{});
while (i < 256) : (i += 1) {
std.log.info("{} -> {}, {d:2}%", .{ i, dist[i], @as(f32, @floatFromInt(dist[i])) / @as(f32, @floatFromInt(counter)) });
}
}
time.sleep_ms(1000);
}
}

@ -0,0 +1,26 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const time = rp2040.time;
const gpio = rp2040.gpio;
const clocks = rp2040.clocks;
const peripherals = microzig.chip.peripherals;
const BUF_LEN = 0x100;
const spi = rp2040.spi.num(0);
// Communicate with another RP2040 over spi
// Slave implementation: https://github.com/raspberrypi/pico-examples/blob/master/spi/spi_master_slave/spi_slave/spi_slave.c
pub fn main() !void {
spi.apply(.{
.clock_config = rp2040.clock_config,
});
var out_buf: [BUF_LEN]u8 = .{ 0xAA, 0xBB, 0xCC, 0xDD } ** (BUF_LEN / 4);
var in_buf: [BUF_LEN]u8 = undefined;
while (true) {
_ = spi.transceive(&out_buf, &in_buf);
time.sleep_ms(1 * 1000);
}
}

@ -0,0 +1,84 @@
//! Hello world for the PIO module: generating a square wave
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const gpio = rp2040.gpio;
const Pio = rp2040.pio.Pio;
const StateMachine = rp2040.pio.StateMachine;
const squarewave_program = blk: {
@setEvalBranchQuota(2000);
break :blk rp2040.pio.assemble(
\\;
\\; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
\\;
\\; SPDX-License-Identifier: BSD-3-Clause
\\;
\\.program squarewave
\\ set pindirs, 1 ; Set pin to output
\\again:
\\ set pins, 1 [1] ; Drive pin high and then delay for one cycle
\\ set pins, 0 ; Drive pin low
\\ jmp again ; Set PC to label `again`
, .{}).get_program_by_name("squarewave");
};
// Pick one PIO instance arbitrarily. We're also arbitrarily picking state
// machine 0 on this PIO instance (the state machines are numbered 0 to 3
// inclusive).
const pio: Pio = .pio0;
const sm: StateMachine = .sm0;
pub fn main() void {
pio.gpio_init(gpio.num(2));
pio.sm_load_and_start_program(sm, squarewave_program, .{
.clkdiv = rp2040.pio.ClkDivOptions.from_float(125),
.pin_mappings = .{
.set = .{
.base = 2,
.count = 1,
},
},
}) catch unreachable;
pio.sm_set_enabled(sm, true);
while (true) {}
//// Load the assembled program directly into the PIO's instruction memory.
//// Each PIO instance has a 32-slot instruction memory, which all 4 state
//// machines can see. The system has write-only access.
//for (squarewave_program.instructions, 0..) |insn, i|
// pio.get_instruction_memory()[i] = insn;
//// Configure state machine 0 to run at sysclk/2.5. The state machines can
//// run as fast as one instruction per clock cycle, but we can scale their
//// speed down uniformly to meet some precise frequency target, e.g. for a
//// UART baud rate. This register has 16 integer divisor bits and 8
//// fractional divisor bits.
//pio.sm_set_clkdiv(sm, .{
// .int = 2,
// .frac = 0x80,
//});
//// There are five pin mapping groups (out, in, set, side-set, jmp pin)
//// which are used by different instructions or in different circumstances.
//// Here we're just using SET instructions. Configure state machine 0 SETs
//// to affect GPIO 0 only; then configure GPIO0 to be controlled by PIO0,
//// as opposed to e.g. the processors.
//pio.gpio_init(2);
//pio.sm_set_pin_mappings(sm, .{
// .out = .{
// .base = 2,
// .count = 1,
// },
//});
//// Set the state machine running. The PIO CTRL register is global within a
//// PIO instance, so you can start/stop multiple state machines
//// simultaneously. We're using the register's hardware atomic set alias to
//// make one bit high without doing a read-modify-write on the register.
//pio.sm_set_enabled(sm, true);
//while (true) {}
}

@ -0,0 +1,147 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const gpio = rp2040.gpio;
const Pio = rp2040.pio.Pio;
const StateMachine = rp2040.pio.StateMachine;
const ws2812_program = blk: {
@setEvalBranchQuota(5000);
break :blk rp2040.pio.assemble(
\\;
\\; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
\\;
\\; SPDX-License-Identifier: BSD-3-Clause
\\;
\\.program ws2812
\\.side_set 1
\\
\\.define public T1 2
\\.define public T2 5
\\.define public T3 3
\\
\\.wrap_target
\\bitloop:
\\ out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
\\ jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
\\do_one:
\\ jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse
\\do_zero:
\\ nop side 0 [T2 - 1] ; Or drive low, for a short pulse
\\.wrap
, .{}).get_program_by_name("ws2812");
};
const pio: Pio = .pio0;
const sm: StateMachine = .sm0;
const led_pin = gpio.num(16);
const brightness: [256]u8 = blk: {
@setEvalBranchQuota(10_000);
const gamma = 2.2;
const max_brightness = 0x10;
var data: [256]u8 = undefined;
for (&data, 0..) |*bit, i| {
const raw_index: f32 = @floatFromInt(i);
const gamma_brightness = std.math.pow(f32, raw_index / 255.0, gamma);
bit.* = @intFromFloat(max_brightness * gamma_brightness);
}
// @compileLog(data);
break :blk data;
};
const RGB = extern struct {
x: u8 = 0x00,
b: u8,
g: u8,
r: u8,
};
inline fn floatToBright(f: f32) u8 {
return brightness[
@intFromFloat(
std.math.clamp(255.0 * f, 0.0, 255.0),
)
];
}
pub fn main() void {
pio.gpio_init(led_pin);
sm_set_consecutive_pindirs(pio, sm, @intFromEnum(led_pin), 1, true);
const cycles_per_bit: comptime_int = ws2812_program.defines[0].value + //T1
ws2812_program.defines[1].value + //T2
ws2812_program.defines[2].value; //T3
const div = @as(f32, @floatFromInt(rp2040.clock_config.sys.?.output_freq)) /
(800_000 * cycles_per_bit);
pio.sm_load_and_start_program(sm, ws2812_program, .{
.clkdiv = rp2040.pio.ClkDivOptions.from_float(div),
.pin_mappings = .{
.side_set = .{
.base = @intFromEnum(led_pin),
.count = 1,
},
},
.shift = .{
.out_shiftdir = .left,
.autopull = true,
.pull_threshold = 24,
.join_tx = true,
},
}) catch unreachable;
pio.sm_set_enabled(sm, true);
var rng_src = std.rand.DefaultPrng.init(0x1234);
const rng = rng_src.random();
var screen: [5][5]RGB = undefined;
for (&screen) |*row| {
for (row) |*pix| {
pix.* = RGB{
.r = brightness[rng.int(u8)],
.g = brightness[rng.int(u8)],
.b = brightness[rng.int(u8)],
};
}
}
while (true) {
screen[rng.intRangeLessThan(u8, 0, 5)][rng.intRangeLessThan(u8, 0, 5)] = RGB{
.r = brightness[rng.int(u8)],
.g = brightness[rng.int(u8)],
.b = brightness[rng.int(u8)],
};
for (@as([25]RGB, @bitCast(screen))) |color| {
pio.sm_blocking_write(sm, @bitCast(color));
}
rp2040.time.sleep_ms(50);
}
}
fn sm_set_consecutive_pindirs(_pio: Pio, _sm: StateMachine, pin: u5, count: u3, is_out: bool) void {
const sm_regs = _pio.get_sm_regs(_sm);
const pinctrl_saved = sm_regs.pinctrl.raw;
sm_regs.pinctrl.modify(.{
.SET_BASE = pin,
.SET_COUNT = count,
});
_pio.sm_exec(_sm, rp2040.pio.Instruction{
.tag = .set,
.delay_side_set = 0,
.payload = .{
.set = .{
.data = @intFromBool(is_out),
.destination = .pindirs,
},
},
});
sm_regs.pinctrl.raw = pinctrl_saved;
}

@ -0,0 +1,49 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const time = rp2040.time;
const gpio = rp2040.gpio;
const clocks = rp2040.clocks;
const led = gpio.num(25);
const uart = rp2040.uart.num(0);
const baud_rate = 115200;
const uart_tx_pin = gpio.num(0);
const uart_rx_pin = gpio.num(1);
pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
std.log.err("panic: {s}", .{message});
@breakpoint();
while (true) {}
}
pub const std_options = struct {
pub const log_level = .debug;
pub const logFn = rp2040.uart.log;
};
pub fn main() !void {
led.set_function(.sio);
led.set_direction(.out);
led.put(1);
uart.apply(.{
.baud_rate = baud_rate,
.tx_pin = uart_tx_pin,
.rx_pin = uart_rx_pin,
.clock_config = rp2040.clock_config,
});
rp2040.uart.init_logger(uart);
var i: u32 = 0;
while (true) : (i += 1) {
led.put(1);
std.log.info("what {}", .{i});
time.sleep_ms(500);
led.put(0);
time.sleep_ms(500);
}
}

@ -0,0 +1,172 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const flash = rp2040.flash;
const time = rp2040.time;
const gpio = rp2040.gpio;
const clocks = rp2040.clocks;
const usb = rp2040.usb;
const led = gpio.num(25);
const uart = rp2040.uart.num(0);
const baud_rate = 115200;
const uart_tx_pin = gpio.num(0);
const uart_rx_pin = gpio.num(1);
// First we define two callbacks that will be used by the endpoints we define next...
fn ep1_in_callback(dc: *usb.DeviceConfiguration, data: []const u8) void {
_ = data;
// The host has collected the data we repeated onto
// EP1! Set up to receive more data on EP1.
usb.Usb.callbacks.usb_start_rx(
dc.endpoints[2], // EP1_OUT_CFG,
64,
);
}
fn ep1_out_callback(dc: *usb.DeviceConfiguration, data: []const u8) void {
// We've gotten data from the host on our custom
// EP1! Set up EP1 to repeat it.
usb.Usb.callbacks.usb_start_tx(
dc.endpoints[3], // EP1_IN_CFG,
data,
);
}
// The endpoints EP0_IN and EP0_OUT are already defined but you can
// add your own endpoints to...
pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{
.descriptor = &usb.EndpointDescriptor{
.length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))),
.descriptor_type = usb.DescType.Endpoint,
.endpoint_address = usb.Dir.Out.endpoint(1),
.attributes = @intFromEnum(usb.TransferType.Bulk),
.max_packet_size = 64,
.interval = 0,
},
.endpoint_control_index = 2,
.buffer_control_index = 3,
.data_buffer_index = 2,
.next_pid_1 = false,
// The callback will be executed if we got an interrupt on EP1_OUT
.callback = ep1_out_callback,
};
pub var EP1_IN_CFG: usb.EndpointConfiguration = .{
.descriptor = &usb.EndpointDescriptor{
.length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))),
.descriptor_type = usb.DescType.Endpoint,
.endpoint_address = usb.Dir.In.endpoint(1),
.attributes = @intFromEnum(usb.TransferType.Bulk),
.max_packet_size = 64,
.interval = 0,
},
.endpoint_control_index = 1,
.buffer_control_index = 2,
.data_buffer_index = 3,
.next_pid_1 = false,
// The callback will be executed if we got an interrupt on EP1_IN
.callback = ep1_in_callback,
};
// This is our device configuration
pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{
.device_descriptor = &.{
.length = @as(u8, @intCast(@sizeOf(usb.DeviceDescriptor))),
.descriptor_type = usb.DescType.Device,
.bcd_usb = 0x0110,
.device_class = 0,
.device_subclass = 0,
.device_protocol = 0,
.max_packet_size0 = 64,
.vendor = 0,
.product = 1,
.bcd_device = 0,
.manufacturer_s = 1,
.product_s = 2,
.serial_s = 0,
.num_configurations = 1,
},
.interface_descriptor = &.{
.length = @as(u8, @intCast(@sizeOf(usb.InterfaceDescriptor))),
.descriptor_type = usb.DescType.Interface,
.interface_number = 0,
.alternate_setting = 0,
// We have two endpoints (EP0 IN/OUT don't count)
.num_endpoints = 2,
.interface_class = 0xff,
.interface_subclass = 0,
.interface_protocol = 0,
.interface_s = 0,
},
.config_descriptor = &.{
.length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor))),
.descriptor_type = usb.DescType.Config,
.total_length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor) + @sizeOf(usb.InterfaceDescriptor) + @sizeOf(usb.EndpointDescriptor) + @sizeOf(usb.EndpointDescriptor))),
.num_interfaces = 1,
.configuration_value = 1,
.configuration_s = 0,
.attributes = 0xc0,
.max_power = 0x32,
},
.lang_descriptor = "\x04\x03\x09\x04", // length || string descriptor (0x03) || Engl (0x0409)
.descriptor_strings = &.{
// ugly unicode :|
"R\x00a\x00s\x00p\x00b\x00e\x00r\x00r\x00y\x00 \x00P\x00i\x00",
"P\x00i\x00c\x00o\x00 \x00T\x00e\x00s\x00t\x00 \x00D\x00e\x00v\x00i\x00c\x00e\x00",
},
// Here we pass all endpoints to the config
// Dont forget to pass EP0_[IN|OUT] in the order seen below!
.endpoints = .{
&usb.EP0_OUT_CFG,
&usb.EP0_IN_CFG,
&EP1_OUT_CFG,
&EP1_IN_CFG,
},
};
pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
std.log.err("panic: {s}", .{message});
@breakpoint();
while (true) {}
}
pub const std_options = struct {
pub const log_level = .debug;
pub const logFn = rp2040.uart.log;
};
pub fn main() !void {
led.set_function(.sio);
led.set_direction(.out);
led.put(1);
uart.apply(.{
.baud_rate = baud_rate,
.tx_pin = uart_tx_pin,
.rx_pin = uart_rx_pin,
.clock_config = rp2040.clock_config,
});
rp2040.uart.init_logger(uart);
// First we initialize the USB clock
rp2040.usb.Usb.init_clk();
// Then initialize the USB device using the configuration defined above
rp2040.usb.Usb.init_device(&DEVICE_CONFIGURATION) catch unreachable;
var old: u64 = time.get_time_since_boot().to_us();
var new: u64 = 0;
while (true) {
// You can now poll for USB events
rp2040.usb.Usb.task(
false, // debug output over UART [Y/n]
) catch unreachable;
new = time.get_time_since_boot().to_us();
if (new - old > 500000) {
old = new;
led.toggle();
}
}
}

@ -0,0 +1,187 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const flash = rp2040.flash;
const time = rp2040.time;
const gpio = rp2040.gpio;
const clocks = rp2040.clocks;
const usb = rp2040.usb;
const led = gpio.num(25);
const uart = rp2040.uart.num(0);
const baud_rate = 115200;
const uart_tx_pin = gpio.num(0);
const uart_rx_pin = gpio.num(1);
// First we define two callbacks that will be used by the endpoints we define next...
fn ep1_in_callback(dc: *usb.DeviceConfiguration, data: []const u8) void {
_ = data;
// The host has collected the data we repeated onto
// EP1! Set up to receive more data on EP1.
usb.Usb.callbacks.usb_start_rx(
dc.endpoints[2], // EP1_OUT_CFG,
64,
);
}
fn ep1_out_callback(dc: *usb.DeviceConfiguration, data: []const u8) void {
// We've gotten data from the host on our custom
// EP1! Set up EP1 to repeat it.
usb.Usb.callbacks.usb_start_tx(
dc.endpoints[3], // EP1_IN_CFG,
data,
);
}
// The endpoints EP0_IN and EP0_OUT are already defined but you can
// add your own endpoints to...
pub var EP1_OUT_CFG: usb.EndpointConfiguration = .{
.descriptor = &usb.EndpointDescriptor{
.length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))),
.descriptor_type = usb.DescType.Endpoint,
.endpoint_address = usb.Dir.Out.endpoint(1),
.attributes = @intFromEnum(usb.TransferType.Interrupt),
.max_packet_size = 64,
.interval = 0,
},
.endpoint_control_index = 2,
.buffer_control_index = 3,
.data_buffer_index = 2,
.next_pid_1 = false,
// The callback will be executed if we got an interrupt on EP1_OUT
.callback = ep1_out_callback,
};
pub var EP1_IN_CFG: usb.EndpointConfiguration = .{
.descriptor = &usb.EndpointDescriptor{
.length = @as(u8, @intCast(@sizeOf(usb.EndpointDescriptor))),
.descriptor_type = usb.DescType.Endpoint,
.endpoint_address = usb.Dir.In.endpoint(1),
.attributes = @intFromEnum(usb.TransferType.Interrupt),
.max_packet_size = 64,
.interval = 0,
},
.endpoint_control_index = 1,
.buffer_control_index = 2,
.data_buffer_index = 3,
.next_pid_1 = false,
// The callback will be executed if we got an interrupt on EP1_IN
.callback = ep1_in_callback,
};
// This is our device configuration
pub var DEVICE_CONFIGURATION: usb.DeviceConfiguration = .{
.device_descriptor = &.{
.length = @as(u8, @intCast(@sizeOf(usb.DeviceDescriptor))),
.descriptor_type = usb.DescType.Device,
.bcd_usb = 0x0200,
.device_class = 0,
.device_subclass = 0,
.device_protocol = 0,
.max_packet_size0 = 64,
.vendor = 0xCafe,
.product = 1,
.bcd_device = 0x0100,
// Those are indices to the descriptor strings
// Make sure to provide enough string descriptors!
.manufacturer_s = 1,
.product_s = 2,
.serial_s = 3,
.num_configurations = 1,
},
.interface_descriptor = &.{
.length = @as(u8, @intCast(@sizeOf(usb.InterfaceDescriptor))),
.descriptor_type = usb.DescType.Interface,
.interface_number = 0,
.alternate_setting = 0,
// We have two endpoints (EP0 IN/OUT don't count)
.num_endpoints = 2,
.interface_class = 3,
.interface_subclass = 0,
.interface_protocol = 0,
.interface_s = 0,
},
.config_descriptor = &.{
.length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor))),
.descriptor_type = usb.DescType.Config,
.total_length = @as(u8, @intCast(@sizeOf(usb.ConfigurationDescriptor) + @sizeOf(usb.InterfaceDescriptor) + @sizeOf(usb.EndpointDescriptor) + @sizeOf(usb.EndpointDescriptor))),
.num_interfaces = 1,
.configuration_value = 1,
.configuration_s = 0,
.attributes = 0xc0,
.max_power = 0x32,
},
.lang_descriptor = "\x04\x03\x09\x04", // length || string descriptor (0x03) || Engl (0x0409)
.descriptor_strings = &.{
// ugly unicode :|
//"R\x00a\x00s\x00p\x00b\x00e\x00r\x00r\x00y\x00 \x00P\x00i\x00",
&usb.utf8ToUtf16Le("Raspberry Pi"),
//"P\x00i\x00c\x00o\x00 \x00T\x00e\x00s\x00t\x00 \x00D\x00e\x00v\x00i\x00c\x00e\x00",
&usb.utf8ToUtf16Le("Pico Test Device"),
//"c\x00a\x00f\x00e\x00b\x00a\x00b\x00e\x00",
&usb.utf8ToUtf16Le("cafebabe"),
},
.hid = .{
.hid_descriptor = &.{
.bcd_hid = 0x0111,
.country_code = 0,
.num_descriptors = 1,
.report_length = 34,
},
.report_descriptor = &usb.hid.ReportDescriptorFidoU2f,
},
// Here we pass all endpoints to the config
// Dont forget to pass EP0_[IN|OUT] in the order seen below!
.endpoints = .{
&usb.EP0_OUT_CFG,
&usb.EP0_IN_CFG,
&EP1_OUT_CFG,
&EP1_IN_CFG,
},
};
pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
std.log.err("panic: {s}", .{message});
@breakpoint();
while (true) {}
}
pub const std_options = struct {
pub const log_level = .debug;
pub const logFn = rp2040.uart.log;
};
pub fn main() !void {
led.set_function(.sio);
led.set_direction(.out);
led.put(1);
uart.apply(.{
.baud_rate = baud_rate,
.tx_pin = uart_tx_pin,
.rx_pin = uart_rx_pin,
.clock_config = rp2040.clock_config,
});
rp2040.uart.init_logger(uart);
// First we initialize the USB clock
rp2040.usb.Usb.init_clk();
// Then initialize the USB device using the configuration defined above
rp2040.usb.Usb.init_device(&DEVICE_CONFIGURATION) catch unreachable;
var old: u64 = time.get_time_since_boot().to_us();
var new: u64 = 0;
while (true) {
// You can now poll for USB events
rp2040.usb.Usb.task(
true, // debug output over UART [Y/n]
) catch unreachable;
new = time.get_time_since_boot().to_us();
if (new - old > 500000) {
old = new;
led.toggle();
}
}
}

@ -0,0 +1,94 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2040 = microzig.hal;
const gpio = rp2040.gpio;
const Pio = rp2040.pio.Pio;
const StateMachine = rp2040.pio.StateMachine;
const ws2812_program = blk: {
@setEvalBranchQuota(5000);
break :blk rp2040.pio.assemble(
\\;
\\; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
\\;
\\; SPDX-License-Identifier: BSD-3-Clause
\\;
\\.program ws2812
\\.side_set 1
\\
\\.define public T1 2
\\.define public T2 5
\\.define public T3 3
\\
\\.wrap_target
\\bitloop:
\\ out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
\\ jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
\\do_one:
\\ jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse
\\do_zero:
\\ nop side 0 [T2 - 1] ; Or drive low, for a short pulse
\\.wrap
, .{}).get_program_by_name("ws2812");
};
const pio: Pio = .pio0;
const sm: StateMachine = .sm0;
const led_pin = gpio.num(23);
pub fn main() void {
pio.gpio_init(led_pin);
sm_set_consecutive_pindirs(pio, sm, @intFromEnum(led_pin), 1, true);
const cycles_per_bit: comptime_int = ws2812_program.defines[0].value + //T1
ws2812_program.defines[1].value + //T2
ws2812_program.defines[2].value; //T3
const div = @as(f32, @floatFromInt(rp2040.clock_config.sys.?.output_freq)) /
(800_000 * cycles_per_bit);
pio.sm_load_and_start_program(sm, ws2812_program, .{
.clkdiv = rp2040.pio.ClkDivOptions.from_float(div),
.pin_mappings = .{
.side_set = .{
.base = @intFromEnum(led_pin),
.count = 1,
},
},
.shift = .{
.out_shiftdir = .left,
.autopull = true,
.pull_threshold = 24,
.join_tx = true,
},
}) catch unreachable;
pio.sm_set_enabled(sm, true);
while (true) {
pio.sm_blocking_write(sm, 0x00ff00 << 8); //red
rp2040.time.sleep_ms(1000);
pio.sm_blocking_write(sm, 0xff0000 << 8); //green
rp2040.time.sleep_ms(1000);
pio.sm_blocking_write(sm, 0x0000ff << 8); //blue
rp2040.time.sleep_ms(1000);
}
}
fn sm_set_consecutive_pindirs(_pio: Pio, _sm: StateMachine, pin: u5, count: u3, is_out: bool) void {
const sm_regs = _pio.get_sm_regs(_sm);
const pinctrl_saved = sm_regs.pinctrl.raw;
sm_regs.pinctrl.modify(.{
.SET_BASE = pin,
.SET_COUNT = count,
});
_pio.sm_exec(_sm, rp2040.pio.Instruction{
.tag = .set,
.delay_side_set = 0,
.payload = .{
.set = .{
.data = @intFromBool(is_out),
.destination = .pindirs,
},
},
});
sm_regs.pinctrl.raw = pinctrl_saved;
}

@ -0,0 +1,47 @@
const std = @import("std");
const stm32 = @import("stm32");
const available_examples = [_]Example{
.{ .name = "stm32f103x8", .target = stm32.chips.stm32f103x8, .file = "src/blinky.zig" },
// TODO: .{ .name = "stm32f303vc", .target = stm32.chips.stm32f303vc, .file = "src/blinky.zig" },
// TODO: .{ .name = "stm32f407vg", .target = stm32.chips.stm32f407vg, .file = "src/blinky.zig" },
// TODO: .{ .name = "stm32f429zit6u", .target = stm32.chips.stm32f429zit6u, .file = "src/blinky.zig" },
// TODO: .{ .name = "stm32f3discovery", .target = stm32.boards.stm32f3discovery, .file = "src/blinky.zig" },
// TODO: .{ .name = "stm32f4discovery", .target = stm32.boards.stm32f4discovery, .file = "src/blinky.zig" },
// TODO: .{ .name = "stm3240geval", .target = stm32.boards.stm3240geval, .file = "src/blinky.zig" },
// TODO: .{ .name = "stm32f429idiscovery", .target = stm32.boards.stm32f429idiscovery, .file = "src/blinky.zig" },
};
pub fn build(b: *std.Build) void {
const microzig = @import("microzig").init(b, "microzig");
const optimize = .ReleaseSmall; // The others are not really an option on AVR
for (available_examples) |example| {
// `addFirmware` basically works like addExecutable, but takes a
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
//
// The target will convey all necessary information on the chip,
// cpu and potentially the board as well.
const firmware = microzig.addFirmware(b, .{
.name = example.name,
.target = example.target,
.optimize = optimize,
.source_file = .{ .path = example.file },
});
// `installFirmware()` is the MicroZig pendant to `Build.installArtifact()`
// and allows installing the firmware as a typical firmware file.
//
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
microzig.installFirmware(b, firmware, .{});
// For debugging, we also always install the firmware as an ELF file
microzig.installFirmware(b, firmware, .{ .format = .elf });
}
}
const Example = struct {
target: @import("microzig").Target,
name: []const u8,
file: []const u8,
};

@ -0,0 +1,14 @@
.{
.name = "microzig-stmicro-stm32-examples",
.version = "0.1.0",
.dependencies = .{
.microzig = .{
.url = "https://github.com/ZigEmbeddedGroup/microzig/archive/c6c9ec4516f57638e751141085c9d76120990312.tar.gz",
.hash = "1220af58bdaa721b8189f3a7adfda660517dd354463463388e96d69fe4ceccf80b92",
},
.stm32 = .{
.url = "https://github.com/ZigEmbeddedGroup/stmicro-stm32/archive/237890d49ee795110a63df2c45bdd6f6a0029a72.tar.gz",
.hash = "1220960897777f9713fa1055ffdf1fbad1518b2f62bd2f2ae39b887821dbf0781df0",
},
},
}

@ -0,0 +1,22 @@
const std = @import("std");
const microzig = @import("microzig");
const stm32 = microzig.hal;
const pin_config = stm32.pins.GlobalConfiguration{
.GPIOC = .{
.PIN13 = .{ .name = "led", .mode = .{ .output = .general_purpose_push_pull } },
},
};
pub fn main() !void {
const pins = pin_config.apply();
while (true) {
var i: u32 = 0;
while (i < 800_000) {
asm volatile ("nop");
i += 1;
}
pins.led.toggle();
}
}
Loading…
Cancel
Save