|
| 1 | +--- |
| 2 | +.title = "Getting Started", |
| 3 | +.date = @date("2024-11-02T00:00:00"), |
| 4 | +.author = "Matthew Knight", |
| 5 | +.draft = false, |
| 6 | +.layout = "index.shtml", |
| 7 | +.description = "MicroZig: Getting Started", |
| 8 | +.tags = [] |
| 9 | +--- |
| 10 | + |
| 11 | +# Getting Started |
| 12 | + |
| 13 | +## Blinky on the Raspberry Pi Pico |
| 14 | + |
| 15 | +This tutorial assumes that you're programming a [Raspberry Pi |
| 16 | +Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/). This hardware |
| 17 | +is by far the best supported in MicroZig. It's a fairly alpha project based on |
| 18 | +a fairly new and breaking language so your mileage may vary. That being said, |
| 19 | +it does support other hardware, such as Microchip's `ATSAMD51J19` which was |
| 20 | +used for the [2024 SYCL](https://sycl.it) |
| 21 | +[Badge](https://github.com/ZigEmbeddedGroup/sycl-badge/blob/main/docs/introduction/). |
| 22 | + |
| 23 | +## Let's Begin |
| 24 | + |
| 25 | +Assuming you've initialized a zig project with `zig init`, or have set one up |
| 26 | +yourself, you can add microzig as a dependency with the following command: |
| 27 | + |
| 28 | +```sh |
| 29 | +zig fetch --save=microzig https://microzig.tech/downloads/microzig/0.13.2/microzig.tar.gz |
| 30 | +``` |
| 31 | + |
| 32 | +Then in your `build.zig`: |
| 33 | + |
| 34 | +```zig |
| 35 | +const std = @import("std"); |
| 36 | +const microzig = @import("microzig"); |
| 37 | + |
| 38 | +const MicroBuild = microzig.MicroBuild(.{ |
| 39 | + .rp2xxx = true, |
| 40 | +}); |
| 41 | + |
| 42 | +pub fn build(b: *std.Build) void { |
| 43 | + const mz_dep = b.dependency("microzig", .{}); |
| 44 | + const mb = MicroBuild.init(b, mz_dep) orelse return; |
| 45 | + |
| 46 | + const firmware = mb.add_firmware(.{ |
| 47 | + .name = "blinky", |
| 48 | + .target = mb.ports.rp2xxx.boards.raspberrypi.pico, |
| 49 | + .optimize = .ReleaseSmall, |
| 50 | + .root_source_file = b.path("src/main.zig"), |
| 51 | + }); |
| 52 | + |
| 53 | + // We call this twice to demonstrate that the default binary output for |
| 54 | + // RP2040 is UF2, but we can also output other formats easily |
| 55 | + mb.install_firmware(firmware, .{ }); |
| 56 | + mb.install_firmware(firmware, .{ .format = .elf }); |
| 57 | +} |
| 58 | +``` |
| 59 | + |
| 60 | +and for your `src/main.zig`, let's start with a classic blinky program. Yes, |
| 61 | +most of the main stdlib is available for use on an MCU with Zig: |
| 62 | + |
| 63 | +```zig |
| 64 | +const std = @import("std"); |
| 65 | +const microzig = @import("microzig"); |
| 66 | +const rp2xxx = microzig.hal; |
| 67 | +const time = rp2xxx.time; |
| 68 | + |
| 69 | +// Compile-time pin configuration |
| 70 | +const pin_config = rp2xxx.pins.GlobalConfiguration{ |
| 71 | + .GPIO25 = .{ |
| 72 | + .name = "led", |
| 73 | + .direction = .out, |
| 74 | + }, |
| 75 | +}; |
| 76 | + |
| 77 | +const pins = pin_config.pins(); |
| 78 | + |
| 79 | +pub fn main() !void { |
| 80 | + pin_config.apply(); |
| 81 | + |
| 82 | + while (true) { |
| 83 | + pins.led.toggle(); |
| 84 | + time.sleep_ms(250); |
| 85 | + } |
| 86 | +} |
| 87 | +``` |
| 88 | + |
| 89 | +Now if you run `zig build`, our extremely simple program will be installed under `zig-out`: |
| 90 | + |
| 91 | +``` |
| 92 | +zig-out |
| 93 | +└── firmware |
| 94 | + ├── blinky.uf2 |
| 95 | + └── blinky.elf |
| 96 | +``` |
| 97 | + |
| 98 | +And if we run the `file` command, often found on Linux and MacOS, on the ELF |
| 99 | +file we'll see that it's targetting ARM!: |
| 100 | + |
| 101 | +``` |
| 102 | +zig-out/firmware/blinky.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped |
| 103 | +``` |
| 104 | + |
| 105 | +## Programming the MCU |
| 106 | + |
| 107 | +To activate the UF2 bootloader, power must be applied to the pico while the |
| 108 | +`BOOTSEL` button is held. This is best done by connecting a button from `RUN` |
| 109 | +to ground, pressing both buttons, and releasing the `RUN` button first, then |
| 110 | +`BOOTSEL`. The other option is to plug/unplug the USB cable which is awkward |
| 111 | +and gets tiresome. |
| 112 | + |
| 113 | +Copy the uf2 file into the mounted drive. Execution should take place immediately. |
| 114 | + |
| 115 | +## Further Resources |
| 116 | + |
| 117 | +- [Zig Language Reference](https://ziglang.org/documentation/0.14.0/) |
0 commit comments