Skip to content

Commit 204d2a6

Browse files
authored
feat: add nxp mcx port (ZigEmbeddedGroup#649)
* feat: add nxp mcx port * refactor: fetch svd from github and rename init -> num * chore: code style + add mcx example to ci
1 parent d138762 commit 204d2a6

16 files changed

Lines changed: 584 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ jobs:
173173
microchip/atsam,
174174
nordic/nrf5x,
175175
nxp/lpc,
176+
nxp/mcx,
176177
stmicro/stm32,
177178
raspberrypi/rp2xxx,
178179
wch/ch32v,

build.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const port_list: []const struct {
2727
.{ .name = "avr", .dep_name = "port/microchip/avr" },
2828
.{ .name = "nrf5x", .dep_name = "port/nordic/nrf5x" },
2929
.{ .name = "lpc", .dep_name = "port/nxp/lpc" },
30+
.{ .name = "mcx", .dep_name = "port/nxp/mcx" },
3031
.{ .name = "rp2xxx", .dep_name = "port/raspberrypi/rp2xxx" },
3132
.{ .name = "stm32", .dep_name = "port/stmicro/stm32" },
3233
.{ .name = "ch32v", .dep_name = "port/wch/ch32v" },

build.zig.zon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
.@"port/microchip/avr" = .{ .path = "port/microchip/avr", .lazy = true },
3030
.@"port/nordic/nrf5x" = .{ .path = "port/nordic/nrf5x", .lazy = true },
3131
.@"port/nxp/lpc" = .{ .path = "port/nxp/lpc", .lazy = true },
32+
.@"port/nxp/mcx" = .{ .path = "port/nxp/mcx", .lazy = true },
3233
.@"port/raspberrypi/rp2xxx" = .{ .path = "port/raspberrypi/rp2xxx", .lazy = true },
3334
.@"port/stmicro/stm32" = .{ .path = "port/stmicro/stm32", .lazy = true },
3435
.@"port/wch/ch32v" = .{ .path = "port/wch/ch32v", .lazy = true },

examples/nxp/mcx/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Examples for NXP MCX port
2+
3+
All examples:
4+
5+
| Example | Description |
6+
| -------------------------------- |--------------------------- |
7+
| [Blinky](src/blinky.zig) | A basic LED blink example |
8+
| [GPIO input](src/gpio_input.zig) | Toggle LED on button press |
9+
10+
## Flashing
11+
12+
You can flash using [NXP's LinkServer](https://www.nxp.com/design/design-center/software/development-software/mcuxpresso-software-and-tools-/linkserver-for-microcontrollers:LINKERSERVER) or [pyOCD](https://pyocd.io/) with a [MCXA CMSIS pack](https://www.keil.arm.com/packs/mcxa153_dfp-nxp/devices/), e.g.:
13+
14+
```sh
15+
zig build -Dexample=blinky -Doptimize=ReleaseSmall
16+
17+
pyocd flash ./zig-out/firmware/blinky.elf --target mcxa153 --quiet
18+
```

examples/nxp/mcx/build.zig

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
const std = @import("std");
2+
const microzig = @import("microzig");
3+
4+
const MicroBuild = microzig.MicroBuild(.{
5+
.mcx = true,
6+
});
7+
8+
pub fn build(b: *std.Build) void {
9+
const optimize = b.standardOptimizeOption(.{});
10+
const maybe_example = b.option([]const u8, "example", "only build matching examples");
11+
12+
const mz_dep = b.dependency("microzig", .{});
13+
const mb = MicroBuild.init(b, mz_dep) orelse return;
14+
15+
const frdm_mcxa153 = mb.ports.mcx.chips.mcxa153;
16+
17+
const available_examples = [_]Example{
18+
.{ .name = "blinky", .target = frdm_mcxa153, .file = "src/blinky.zig" },
19+
.{ .name = "gpio_input", .target = frdm_mcxa153, .file = "src/gpio_input.zig" },
20+
};
21+
22+
for (available_examples) |example| {
23+
// If we specify example, only select the ones that match
24+
if (maybe_example) |selected_example|
25+
if (!std.mem.containsAtLeast(u8, example.name, 1, selected_example))
26+
continue;
27+
28+
// `add_firmware` basically works like addExecutable, but takes a
29+
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
30+
//
31+
// The target will convey all necessary information on the chip,
32+
// cpu and potentially the board as well.
33+
const firmware = mb.add_firmware(.{
34+
.name = example.name,
35+
.target = example.target,
36+
.optimize = optimize,
37+
.root_source_file = b.path(example.file),
38+
});
39+
40+
// `install_firmware()` is the MicroZig pendant to `Build.installArtifact()`
41+
// and allows installing the firmware as a typical firmware file.
42+
//
43+
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
44+
mb.install_firmware(firmware, .{});
45+
46+
// For debugging, we also always install the firmware as an ELF file
47+
mb.install_firmware(firmware, .{ .format = .elf });
48+
}
49+
}
50+
51+
const Example = struct {
52+
target: *const microzig.Target,
53+
name: []const u8,
54+
file: []const u8,
55+
};

examples/nxp/mcx/build.zig.zon

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.{
2+
.name = .examples_nxp_mcx,
3+
.version = "0.0.0",
4+
.fingerprint = 0x345c53e39b0295f5,
5+
.minimum_zig_version = "0.14.1",
6+
.dependencies = .{
7+
.microzig = .{ .path = "../../.." },
8+
},
9+
.paths = .{
10+
"build.zig",
11+
"build.zig.zon",
12+
"src",
13+
"README.md",
14+
},
15+
}

examples/nxp/mcx/src/blinky.zig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const microzig = @import("microzig");
2+
const hal = microzig.hal;
3+
4+
const port3 = hal.port.num(3);
5+
const pin_led_red = port3.get_gpio(12);
6+
7+
pub fn main() void {
8+
port3.init();
9+
10+
pin_led_red.init();
11+
pin_led_red.set_direction(.out);
12+
pin_led_red.put(1); // Turn off
13+
14+
while (true) {
15+
pin_led_red.toggle();
16+
delay_cycles(96_000_000 / 80);
17+
}
18+
}
19+
20+
fn delay_cycles(cycles: u32) void {
21+
for (0..cycles) |_| {
22+
asm volatile ("nop");
23+
}
24+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const microzig = @import("microzig");
2+
const hal = microzig.hal;
3+
4+
pub const microzig_options = microzig.Options{
5+
.interrupts = .{ .GPIO3 = .{ .c = gpio3_irq_handler } },
6+
};
7+
8+
const port3 = hal.port.num(3);
9+
const pin_led_red = port3.get_gpio(12);
10+
const pin_button = port3.get_gpio(29);
11+
12+
pub fn main() void {
13+
microzig.interrupt.enable_interrupts();
14+
microzig.interrupt.enable(.GPIO3);
15+
16+
port3.init();
17+
18+
pin_led_red.init();
19+
pin_led_red.set_direction(.out);
20+
pin_led_red.put(1);
21+
22+
pin_button.init();
23+
pin_button.set_direction(.in);
24+
pin_button.set_interrupt_config(.interrupt_rising_edge);
25+
26+
while (true) {
27+
const is_pressed: *volatile bool = &button_pressed;
28+
if (is_pressed.*) {
29+
pin_led_red.toggle();
30+
is_pressed.* = false;
31+
}
32+
}
33+
}
34+
35+
var button_pressed: bool = false;
36+
fn gpio3_irq_handler() callconv(.c) void {
37+
pin_button.clear_interrupt_flag();
38+
39+
const is_pressed: *volatile bool = &button_pressed;
40+
is_pressed.* = true;
41+
}

port/nxp/mcx/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# NXP MCX Series
2+
3+
HAL and register definitions for NXP MCX series MCUs. Currently only supports MCXA153.
4+
5+
Register defintions are taken from: https://github.com/nxp-mcuxpresso/mcux-soc-svd/

port/nxp/mcx/build.zig

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const std = @import("std");
2+
const microzig = @import("microzig/build-internals");
3+
4+
const Self = @This();
5+
6+
chips: struct {
7+
mcxa153: *const microzig.Target,
8+
},
9+
10+
boards: struct {
11+
frdm_mcxa153: *const microzig.Target,
12+
},
13+
14+
pub fn init(dep: *std.Build.Dependency) Self {
15+
const b = dep.builder;
16+
17+
const mcux_soc_svd = b.dependency("mcux-soc-svd", .{});
18+
19+
const chip_mcxa153: microzig.Target = .{
20+
.dep = dep,
21+
.preferred_binary_format = .elf,
22+
.zig_target = .{
23+
.cpu_arch = .thumb,
24+
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m33 },
25+
.os_tag = .freestanding,
26+
.abi = .eabi,
27+
},
28+
.chip = .{
29+
.name = "MCXA153",
30+
.register_definition = .{ .svd = mcux_soc_svd.path("MCXA153/MCXA153.xml") },
31+
.memory_regions = &.{
32+
.{ .tag = .flash, .offset = 0x00000000, .length = 128 * 1024, .access = .rx },
33+
.{ .tag = .ram, .offset = 0x20000000, .length = 24 * 1024, .access = .rw },
34+
},
35+
},
36+
.hal = .{ .root_source_file = b.path("src/hal.zig") },
37+
};
38+
39+
return .{
40+
.chips = .{
41+
.mcxa153 = chip_mcxa153.derive(.{}),
42+
},
43+
.boards = .{
44+
.frdm_mcxa153 = chip_mcxa153.derive(.{
45+
.board = .{
46+
.name = "FRDM Development Board for MCX A153",
47+
.url = "https://www.nxp.com/part/FRDM-MCXA153",
48+
.root_source_file = b.path("src/boards/frdm_mcxa153.zig"),
49+
},
50+
}),
51+
},
52+
};
53+
}
54+
55+
pub fn build(b: *std.Build) void {
56+
_ = b;
57+
}

0 commit comments

Comments
 (0)