Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ jobs:
[
espressif/esp,
gigadevice/gd32,
#microchip/avr,
hdsc/hc32l110,
#microchip/avr,
microchip/atsam,
nordic/nrf5x,
nxp/lpc,
Expand Down
1 change: 1 addition & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const port_list: []const struct {
} = &.{
.{ .name = "esp", .dep_name = "port/espressif/esp" },
.{ .name = "gd32", .dep_name = "port/gigadevice/gd32" },
.{ .name = "hc32l110", .dep_name = "port/hdsc/hc32l110" },
.{ .name = "atsam", .dep_name = "port/microchip/atsam" },
.{ .name = "avr", .dep_name = "port/microchip/avr" },
.{ .name = "nrf5x", .dep_name = "port/nordic/nrf5x" },
Expand Down
1 change: 1 addition & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
// ports
.@"port/espressif/esp" = .{ .path = "port/espressif/esp", .lazy = true },
.@"port/gigadevice/gd32" = .{ .path = "port/gigadevice/gd32", .lazy = true },
.@"port/hdsc/hc32l110" = .{ .path = "port/hdsc/hc32l110", .lazy = true },
.@"port/microchip/atsam" = .{ .path = "port/microchip/atsam", .lazy = true },
.@"port/microchip/avr" = .{ .path = "port/microchip/avr", .lazy = true },
.@"port/nordic/nrf5x" = .{ .path = "port/nordic/nrf5x", .lazy = true },
Expand Down
16 changes: 16 additions & 0 deletions core/src/mmio.zig
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,21 @@ pub fn Mmio(comptime PackedT: type) type {
}
write(addr, val);
}

pub inline fn write_bit(addr: *volatile Self, offset: u5, value: u1) void {
if (value == 1) {
addr.raw |= 1 << offset;
} else {
addr.raw &= ~@as(IntT, 1 << offset);
}
}

pub inline fn read_bit(addr: *volatile Self, offset: u5) u1 {
return @truncate(addr.raw >> offset);
}

pub inline fn toggle_bit(addr: *volatile Self, offset: u5) void {
addr.raw ^= 1 << offset;
}
};
}
1 change: 1 addition & 0 deletions examples/hdsc/hc32l110/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Examples for the BSP `hdsc-hc32l110`
44 changes: 44 additions & 0 deletions examples/hdsc/hc32l110/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const std = @import("std");
const microzig = @import("microzig");

const MicroBuild = microzig.MicroBuild(.{
.hc32l110 = true,
});

pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{});
const maybe_example = b.option([]const u8, "example", "only build matching examples");

const mz_dep = b.dependency("microzig", .{});
const mb = MicroBuild.init(b, mz_dep) orelse return;

const rtt = b.dependency("rtt", .{});

const examples: []const Example = &.{
.{ .name = "blinky", .file = "src/blinky.zig" },
.{ .name = "crc16", .file = "src/crc16.zig" },
.{ .name = "i2c_ssd1306", .file = "src/i2c_ssd1306.zig" },
};

for (examples) |example| {
if (maybe_example) |selected_example|
if (!std.mem.containsAtLeast(u8, example.name, 1, selected_example))
continue;

const firmware = mb.add_firmware(.{
.name = example.name,
.target = mb.ports.hc32l110.chips.hc32l110x6,
.optimize = optimize,
.root_source_file = b.path(example.file),
});
firmware.add_app_import("rtt", rtt.module("rtt"), .{});

mb.install_firmware(firmware, .{});
mb.install_firmware(firmware, .{ .format = .elf });
}
}

const Example = struct {
name: []const u8,
file: []const u8,
};
18 changes: 18 additions & 0 deletions examples/hdsc/hc32l110/build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.{
.name = .examples_hdsc_hc32l110,
.fingerprint = 0x6b64a904e57948a3,
.version = "0.0.0",
.dependencies = .{
.microzig = .{ .path = "../../.." },
.rtt = .{
.url = "git+https://github.com/haydenridd/zig-rtt#b21fa1b54176e9aa5d17aefe4a7c4e0d9a89a09e",
.hash = "rtt-0.0.0-s7auv1V5AAAtPzKYj-8Kbj7dD1JPkDJBsVxrKGfnIwqj",
},
},
.paths = .{
"README.md",
"build.zig",
"build.zig.zon",
"src",
},
}
20 changes: 20 additions & 0 deletions examples/hdsc/hc32l110/src/blinky.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const std = @import("std");
const microzig = @import("microzig");
const hal = microzig.hal;
const time = hal.time;
const clocks = hal.clocks;
const gpio = hal.gpio;

const led = gpio.num(3, 6);

pub fn main() !void {
clocks.gate.enable(.Gpio);

led.init(.out);
led.put(0);

while (true) {
time.sleep_ms(250);
led.toggle();
}
}
17 changes: 17 additions & 0 deletions examples/hdsc/hc32l110/src/crc16.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const std = @import("std");
const microzig = @import("microzig");
const hal = microzig.hal;
const clocks = hal.clocks;
const crc16 = hal.crc16;

pub fn main() !void {
clocks.gate.enable(.Crc);

const value = crc16.calculate(u8, &.{ 0xDE, 0xAD, 0xBE, 0xEF });
if (value != 0xE5CB) @panic("invalid value");

if (!crc16.check(u8, &.{ 0xDE, 0xAD, 0xBE, 0xEF }, 0xE5CB))
@panic("invalid value");

while (true) {}
}
56 changes: 56 additions & 0 deletions examples/hdsc/hc32l110/src/i2c_ssd1306.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const std = @import("std");
const microzig = @import("microzig");

const hal = microzig.hal;
const time = microzig.time;
const i2c = hal.i2c;
const gpio = hal.gpio;
const clocks = hal.clocks;
const peripherals = microzig.chip.peripherals;

const drivers = microzig.drivers;
const display = drivers.display;
const ssd1306 = display.ssd1306;

const i2c0 = i2c.instance.num(0);

const sda_pin = gpio.num(0, 1);
const scl_pin = gpio.num(0, 2);

var framebuffer: drivers.display.ssd1306.Framebuffer = .init(.black);

pub fn main() !void {
clocks.gate.enable(.Gpio);
clocks.gate.enable(.I2c);

inline for (&.{ scl_pin, sda_pin }) |pin| {
pin.set_direction(.out);
pin.set_pull(.disabled);
pin.set_open_drain(.enabled);
pin.set_drive_strength(.normal);
pin.set_analog(.disabled);
}
// TODO:
sda_pin.set_function(2);
scl_pin.set_function(2);

try i2c0.apply(.{ .baud = 32 });
i2c0.enable();

const i2c_device = i2c0.device(.new(0x3c));
const disp = ssd1306.init(.i2c, i2c_device, null) catch |err|
switch (err) {
error.Timeout => while (true) {},
else => return err,
};

var color: display.colors.BlackWhite = .white;

while (true) {
framebuffer.clear(color);
color = if (color == .black) .white else .black;

try disp.write_full_display(framebuffer.bit_stream());
hal.time.sleep_ms(100);
}
}
34 changes: 34 additions & 0 deletions port/hdsc/hc32l110/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# hdsc-hc32l110

HAL and register definitions for the HC32L110 family of microcontrollers

## Status
- [ ] adc
- [ ] adt
- [-] clocks
- [x] crc
- [ ] flash
- [x] gpio
- [-] i2c
- [x] master
- [ ] slave
- [ ] irq
- [ ] lpm - Low Power Management
- [ ] lpt - Low Power Timer
- [ ] lpuart - Low Power UART
- [ ] lvd - Lov Voltage Detector
- [ ] pca - Programmable Counter Array
- [ ] rtc
- [ ] spi
- [ ] master
- [ ] slave
- [ ] trim - Clock Trimming
- [ ] timers
- [ ] uart
- [ ] vc - Voltage Comparator
- [ ] wdt

Legend:
- [ ] nothing implemented
- [-] partially implemented and working ish
- [x] implemented and tested on real hardware
86 changes: 86 additions & 0 deletions port/hdsc/hc32l110/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
const std = @import("std");
const microzig = @import("microzig/build-internals");

const Self = @This();

chips: struct {
hc32l110x4: *const microzig.Target,
hc32l110x6: *const microzig.Target,
},

boards: struct {
// lilygo: struct {
// t_hc32: *const microzig.Target,
// },
},

pub fn init(dep: *std.Build.Dependency) Self {
const b = dep.builder;

const hal: microzig.HardwareAbstractionLayer = .{
.root_source_file = b.path("src/hal.zig"),
};

const chip_hc32l110x4: microzig.Target = .{
.dep = dep,
.preferred_binary_format = .{ .bin = {} },
.zig_target = .{
.cpu_arch = .thumb,
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m0plus },
.os_tag = .freestanding,
.abi = .eabi,
},
.chip = .{
.name = "HDSC_HC32L110",
.register_definition = .{ .svd = b.path("src/chips/HC32L110.svd") },
.memory_regions = &.{
.{ .kind = .flash, .offset = 0x00000000, .length = 16 * 1024 },
.{ .kind = .ram, .offset = 0x20000000, .length = 2 * 1024 },
},
.patches = @import("patches/hc32l110.zig").patches,
},
.hal = hal,
};

const chip_hc32l110x6: microzig.Target = .{
.dep = dep,
.preferred_binary_format = .{ .bin = {} },
.zig_target = .{
.cpu_arch = .thumb,
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m0plus },
.os_tag = .freestanding,
.abi = .eabi,
},
.chip = .{
.name = "HDSC_HC32L110",
.register_definition = .{ .svd = b.path("src/chips/HC32L110.svd") },
.memory_regions = &.{
.{ .kind = .flash, .offset = 0x00000000, .length = 32 * 1024 },
.{ .kind = .ram, .offset = 0x20000000, .length = 4 * 1024 },
},
.patches = @import("patches/hc32l110.zig").patches,
},
.hal = hal,
};

return .{
.chips = .{
.hc32l110x4 = chip_hc32l110x4.derive(.{}),
.hc32l110x6 = chip_hc32l110x6.derive(.{}),
},
.boards = .{},
};
}

pub fn build(b: *std.Build) !void {
const optimize = b.standardOptimizeOption(.{});

const unit_tests = b.addTest(.{
.root_source_file = b.path("src/hal.zig"),
.optimize = optimize,
});

const unit_tests_run = b.addRunArtifact(unit_tests);
const test_step = b.step("test", "Run platform agnostic unit tests");
test_step.dependOn(&unit_tests_run.step);
}
14 changes: 14 additions & 0 deletions port/hdsc/hc32l110/build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.{
.name = .microzig_port_hdsc_hc32l110,
.fingerprint = 0x75d5d0484fa537e9,
.version = "0.0.0",
.dependencies = .{
.@"microzig/build-internals" = .{ .path = "../../../build-internals" },
},
.paths = .{
"README.md",
"build.zig.zon",
"build.zig",
"src",
},
}
17 changes: 17 additions & 0 deletions port/hdsc/hc32l110/patches/hc32l110.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const Patch = @import("microzig/build-internals").Patch;

pub const patches: []const Patch = &.{
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 0, .name = "PORT0" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 1, .name = "PORT1" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 2, .name = "PORT2" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 3, .name = "PORT3" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 6, .name = "UART0" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 7, .name = "UART1" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 8, .name = "LPUART" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 10, .name = "SPI" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 12, .name = "I2C" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 14, .name = "TIM0" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 15, .name = "TIM1" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 16, .name = "TIM2" } },
.{ .add_interrupt = .{ .device_name = "HDSC_HC32L110", .idx = 17, .name = "LPTIM" } },
};
Loading
Loading