Skip to content

Commit d6f2cf5

Browse files
committed
[hdsc] HC32L110 bring up
1 parent 7aad8aa commit d6f2cf5

39 files changed

+12130
-1
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ jobs:
135135
[
136136
espressif/esp,
137137
gigadevice/gd32,
138-
#microchip/avr,
138+
hdsc/hc32l110,
139+
#microchip/avr,
139140
microchip/atsam,
140141
nordic/nrf5x,
141142
nxp/lpc,

build.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const port_list: []const struct {
2121
} = &.{
2222
.{ .name = "esp", .dep_name = "port/espressif/esp" },
2323
.{ .name = "gd32", .dep_name = "port/gigadevice/gd32" },
24+
.{ .name = "hc32l110", .dep_name = "port/hdsc/hc32l110" },
2425
.{ .name = "atsam", .dep_name = "port/microchip/atsam" },
2526
.{ .name = "avr", .dep_name = "port/microchip/avr" },
2627
.{ .name = "nrf5x", .dep_name = "port/nordic/nrf5x" },

build.zig.zon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
// ports
2424
.@"port/espressif/esp" = .{ .path = "port/espressif/esp", .lazy = true },
2525
.@"port/gigadevice/gd32" = .{ .path = "port/gigadevice/gd32", .lazy = true },
26+
.@"port/hdsc/hc32l110" = .{ .path = "port/hdsc/hc32l110", .lazy = true },
2627
.@"port/microchip/atsam" = .{ .path = "port/microchip/atsam", .lazy = true },
2728
.@"port/microchip/avr" = .{ .path = "port/microchip/avr", .lazy = true },
2829
.@"port/nordic/nrf5x" = .{ .path = "port/nordic/nrf5x", .lazy = true },

examples/hdsc/hc32l110/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Examples for the BSP `hdsc-hc32l110`

examples/hdsc/hc32l110/build.zig

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
const std = @import("std");
2+
const microzig = @import("microzig");
3+
4+
const MicroBuild = microzig.MicroBuild(.{
5+
.hc32l110 = 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 examples: []const Example = &.{
16+
// .{ .name = "adc", .file = "src/adc.zig" },
17+
// .{ .name = "i2c-bus-scan", .file = "src/i2c_bus_scan.zig" },
18+
// .{ .name = "pwm", .file = "src/pwm.zig" },
19+
// .{ .name = "uart-echo", .file = "src/uart_echo.zig" },
20+
// .{ .name = "uart-log", .file = "src/uart_log.zig" },
21+
// .{ .name = "spi-master", .file = "src/spi_master.zig" },
22+
// .{ .name = "spi-slave", .file = "src/spi_slave.zig" },
23+
// .{ .name = "squarewave", .file = "src/squarewave.zig" },
24+
// .{ .name = "ws2812", .file = "src/ws2812.zig" },
25+
.{ .name = "blinky", .file = "src/blinky.zig" },
26+
// .{ .name = "gpio-clock-output", .file = "src/gpio_clock_output.zig" },
27+
// .{ .name = "changing-system-clocks", .file = "src/changing_system_clocks.zig" },
28+
// .{ .name = "custom-clock-config", .file = "src/custom_clock_config.zig" },
29+
// .{ .name = "watchdog-timer", .file = "src/watchdog_timer.zig" },
30+
// .{ .name = "interrupts", .file = "src/interrupts.zig" },
31+
// .{ .name = "stepper_driver", .file = "src/stepper_driver.zig" },
32+
// .{ .name = "stepper_driver_dumb", .file = "src/stepper_driver_dumb.zig" },
33+
// .{ .name = "usb-cdc", .file = "src/usb_cdc.zig" },
34+
// .{ .name = "dma", .file = "src/dma.zig" },
35+
};
36+
37+
for (examples) |example| {
38+
// If we specify example, only select the ones that match
39+
if (maybe_example) |selected_example|
40+
if (!std.mem.containsAtLeast(u8, example.name, 1, selected_example))
41+
continue;
42+
43+
// `add_firmware` basically works like addExecutable, but takes a
44+
// `microzig.Target` for target instead of a `std.zig.CrossTarget`.
45+
//
46+
// The target will convey all necessary information on the chip,
47+
// cpu and potentially the board as well.
48+
const firmware = mb.add_firmware(.{
49+
.name = example.name,
50+
.target = mb.ports.hc32l110.chips.hc32l110x4,
51+
.optimize = optimize,
52+
.root_source_file = b.path(example.file),
53+
});
54+
// firmware.artifact.want_lto = true;
55+
56+
// `install_firmware()` is the MicroZig pendant to `Build.installArtifact()`
57+
// and allows installing the firmware as a typical firmware file.
58+
//
59+
// This will also install into `$prefix/firmware` instead of `$prefix/bin`.
60+
mb.install_firmware(firmware, .{});
61+
62+
// For debugging, we also always install the firmware as an ELF file
63+
mb.install_firmware(firmware, .{ .format = .elf });
64+
}
65+
}
66+
67+
const Example = struct {
68+
name: []const u8,
69+
file: []const u8,
70+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.{
2+
.name = .examples_hdsc_hc32l110,
3+
.fingerprint = 0x6b64a904e57948a3,
4+
.version = "0.0.0",
5+
.dependencies = .{
6+
.microzig = .{ .path = "../../.." },
7+
},
8+
.paths = .{
9+
"README.md",
10+
"build.zig",
11+
"build.zig.zon",
12+
"src",
13+
},
14+
}

examples/hdsc/hc32l110/src/adc.zig

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//! This example takes periodic samples of the temperature sensor and
2+
//! prints it to the UART using the stdlib logging facility.
3+
const std = @import("std");
4+
const microzig = @import("microzig");
5+
const rp2xxx = microzig.hal;
6+
const gpio = rp2xxx.gpio;
7+
const adc = rp2xxx.adc;
8+
const time = rp2xxx.time;
9+
10+
const uart = rp2xxx.uart.instance.num(0);
11+
const baud_rate = 115200;
12+
const uart_tx_pin = gpio.num(0);
13+
14+
pub const microzig_options = microzig.Options{
15+
.logFn = rp2xxx.uart.logFn,
16+
};
17+
18+
pub fn main() !void {
19+
// init uart logging
20+
uart_tx_pin.set_function(.uart);
21+
uart.apply(.{
22+
.baud_rate = baud_rate,
23+
.clock_config = rp2xxx.clock_config,
24+
});
25+
rp2xxx.uart.init_logger(uart);
26+
27+
adc.apply(.{
28+
.temp_sensor_enabled = true,
29+
});
30+
31+
while (true) : (time.sleep_ms(1000)) {
32+
const sample = adc.convert_one_shot_blocking(.temp_sensor) catch {
33+
std.log.err("conversion failed!", .{});
34+
continue;
35+
};
36+
37+
std.log.info("temp value: {}", .{sample});
38+
}
39+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const std = @import("std");
2+
const microzig = @import("microzig");
3+
const hc32l110 = microzig.hal;
4+
const time = hc32l110.time;
5+
const gpio = hc32l110.gpio;
6+
7+
const led = gpio.num(1, 1);
8+
pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
9+
_ = message;
10+
while (true) {}
11+
}
12+
13+
pub fn main() !void {
14+
microzig.chip.peripherals.CLOCK.PERI_CLKEN.modify(.{ .GPIO = 1 });
15+
led.set_function(0);
16+
led.set_direction(.out);
17+
led.put(0);
18+
while (true) {
19+
time.sleep_ms(250);
20+
led.toggle();
21+
}
22+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
const std = @import("std");
2+
const microzig = @import("microzig");
3+
const rp2xxx = microzig.hal;
4+
const gpio = rp2xxx.gpio;
5+
const time = rp2xxx.time;
6+
const clocks = rp2xxx.clocks;
7+
8+
/// The HAL provides a convenvience function for detecting which of the RP2XXX
9+
/// family you're currently compiling for.
10+
const chip = rp2xxx.compatibility.chip;
11+
12+
// Use the system() preset helper to change the SYS and REF clock frequencies from default
13+
const system_clock_cfg = clocks.config.preset.system(
14+
// Reduce the system clock by a factor of 4 (different default clock speeds for RP2350/RP2040)
15+
switch (chip) {
16+
.RP2040 => 125_000_000 / 4,
17+
.RP2350 => 150_000_000 / 4,
18+
},
19+
// Reduce reference clock by a factor of 3
20+
12_000_000 / 3,
21+
);
22+
23+
// Have to override init() so we can apply our own custom pre-main startup procedure
24+
pub fn init() void {
25+
// The default init_sequence works fine here, we just want to swap in our own clock config
26+
rp2xxx.init_sequence(system_clock_cfg);
27+
}
28+
29+
pub fn main() !void {
30+
// Don't forget to bring a blinky!
31+
const led_gpio = gpio.num(25);
32+
led_gpio.set_direction(.out);
33+
led_gpio.set_function(.sio);
34+
led_gpio.put(1);
35+
36+
// See gpio_clock_output.zig for how you could MUX out some of these clocks
37+
// to GPIOs for oscilloscope confirmation!
38+
while (true) {
39+
led_gpio.toggle();
40+
time.sleep_ms(1000);
41+
}
42+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
const std = @import("std");
2+
const microzig = @import("microzig");
3+
const rp2xxx = microzig.hal;
4+
const gpio = rp2xxx.gpio;
5+
const time = rp2xxx.time;
6+
const clocks = rp2xxx.clocks;
7+
const GlobalConfig = clocks.config.Global;
8+
const gpout0_pin = gpio.num(21);
9+
const Pin = gpio.Pin;
10+
11+
/// The HAL provides a convenvience function for detecting which of the RP2XXX
12+
/// family you're currently compiling for.
13+
const chip = rp2xxx.compatibility.chip;
14+
15+
const xosc_freq = microzig.board.xosc_freq;
16+
17+
/// Define an entirely custom clock configuration for the system
18+
/// that changes which clocks are driven from where.
19+
///
20+
/// NOTE: It is very easy to create bogus clock configurations that don't
21+
/// drive the peripheral blocks correctly (or at all) so make sure
22+
/// you know what you're doing if you use this low level interface!
23+
const system_clock_cfg: GlobalConfig = val: {
24+
var temp: GlobalConfig = .{
25+
26+
// Divide our reference clock by 2 to be 6 MHz for fun
27+
.ref = .{
28+
.input = .{
29+
.source = .src_xosc,
30+
.freq = xosc_freq,
31+
},
32+
.integer_divisor = 2,
33+
},
34+
35+
// Change our PLL frequency to be 100MHz instead
36+
.pll_sys = .{
37+
.refdiv = 1,
38+
.fbdiv = 100,
39+
.postdiv1 = 6,
40+
.postdiv2 = 2,
41+
},
42+
43+
// Drive SYS off the PLL_SYS
44+
.sys = .{
45+
.input = .{
46+
.source = .pll_sys,
47+
.freq = 100_000_000,
48+
},
49+
.integer_divisor = 1,
50+
},
51+
52+
// ADC and USB peripherals have to run off 48MHz clock, so these are unchanged
53+
.pll_usb = .{
54+
.refdiv = 1,
55+
.fbdiv = 40,
56+
.postdiv1 = 5,
57+
.postdiv2 = 2,
58+
},
59+
60+
.usb = .{
61+
.input = .{
62+
.source = .pll_usb,
63+
.freq = 48_000_000,
64+
},
65+
.integer_divisor = 1,
66+
},
67+
68+
.adc = .{
69+
.input = .{
70+
.source = .pll_usb,
71+
.freq = 48_000_000,
72+
},
73+
.integer_divisor = 1,
74+
},
75+
76+
// Change peri to also run off XOSC, not neccessarily reccomended, but interesting!
77+
.peri = .{
78+
.input = .{
79+
.source = .src_xosc,
80+
.freq = xosc_freq,
81+
},
82+
.integer_divisor = 1,
83+
},
84+
};
85+
86+
// GlobalConfig has a slight difference between RP2350 (has HSTX) and RP2040 (has RTC)
87+
switch (chip) {
88+
.RP2040 => {
89+
// Drive RTC off XOSC / 3 for a change of pace!
90+
temp.rtc = .{
91+
.input = .{
92+
.source = .src_xosc,
93+
.freq = xosc_freq,
94+
},
95+
.integer_divisor = 3,
96+
};
97+
},
98+
.RP2350 => {
99+
// Drive HSTX off SYS
100+
temp.hstx = .{
101+
.input = .{
102+
.source = .clk_sys,
103+
.freq = 100_000_000,
104+
},
105+
.integer_divisor = 1,
106+
};
107+
},
108+
}
109+
break :val temp;
110+
};
111+
112+
// Have to override init() so we can apply our own custom pre-main startup procedure
113+
pub fn init() void {
114+
// The default init_sequence works fine here, we just want to swap in our own clock config
115+
rp2xxx.init_sequence(system_clock_cfg);
116+
}
117+
118+
pub fn main() !void {
119+
// Don't forget to bring a blinky!
120+
const led_gpio = gpio.num(25);
121+
led_gpio.set_direction(.out);
122+
led_gpio.set_function(.sio);
123+
led_gpio.put(1);
124+
125+
// See gpio_clock_output.zig for how you could MUX out some of these clocks
126+
// to GPIOs for oscilloscope confirmation!
127+
128+
while (true) {
129+
led_gpio.toggle();
130+
time.sleep_ms(1000);
131+
}
132+
}

0 commit comments

Comments
 (0)