add chip and board definitions (#1)

wch-ch32v003
Matt Knight 2 years ago committed by GitHub
parent 42c7a62a3f
commit fe247e6669
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,4 +1,4 @@
Copyright (c) 2022 <name> Copyright (c) 2022 Zig Embedded Group Contributors
This software is provided 'as-is', without any express or implied warranty. In This software is provided 'as-is', without any express or implied warranty. In
no event will the authors be held liable for any damages arising from the use no event will the authors be held liable for any damages arising from the use

@ -1,6 +1,3 @@
= Hardware Support Package Template = NXP LPC Hardware Support Package
1. Update LICENSE file Please see https://github.com/ZigEmbeddedGroup/lpcboot[lpcboot] as well
2. Update `microzig` submodule under `deps/`
3. Add chips/boards/hals
4. Set up buildkite pipeline

@ -1,6 +1,13 @@
const std = @import("std"); const std = @import("std");
const microzig = @import("../deps/microzig/src/main.zig"); const micro = @import("../deps/microzig/src/main.zig");
const chips = @import("chips.zig");
fn root_dir() []const u8 { fn root_dir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse ".";
} }
pub const mbed_lpc1768 = micro.Board{
.name = "mbed LPC1768",
.source = .{ .path = root_dir() ++ "/boards/mbed_LPC1768.zig" },
.chip = chips.lpc176x5x,
};

@ -0,0 +1,84 @@
pub const chip = @import("chip");
pub const micro = @import("microzig");
pub const clock_frequencies = .{
.cpu = 100_000_000, // 100 Mhz
};
pub fn debug_write(string: []const u8) void {
const clk_pin = micro.Pin("DIP5");
const dat_pin = micro.Pin("DIP6");
const clk = micro.core.experimental.Gpio(clk_pin, .{ .mode = .output, .initial_state = .low });
const dat = micro.core.experimental.Gpio(dat_pin, .{ .mode = .output, .initial_state = .low });
clk.init();
dat.init();
micro.debug.busy_sleep(1_000);
for (string) |c| {
comptime var i: usize = 128;
inline while (i > 0) : (i = i >> 1) {
if ((c & i) != 0) {
dat.write(.high);
} else {
dat.write(.low);
}
clk.write(.high);
micro.debug.busy_sleep(1_000);
clk.write(.low);
micro.debug.busy_sleep(1_000);
}
}
dat.write(.low);
clk.write(.low);
}
pub const pin_map = .{
// Onboard-LEDs
.@"LED-1" = "P1.18",
.@"LED-2" = "P1.20",
.@"LED-3" = "P1.21",
.@"LED-4" = "P1.23",
.LED_LINK = "P1.25",
.LED_SPEED = "P1.26",
// Ethernet
.@"TD+" = "P1.0",
.@"TD-" = "P1.1",
.@"RD+" = "P1.9",
.@"RD-" = "P1.10",
// USB
.@"D+" = "P0.29",
.@"D-" = "P0.30",
// GPIO pins
.DIP5 = "P0.9",
.DIP6 = "P0.8",
.DIP7 = "P0.7",
.DIP8 = "P0.6",
.DIP9 = "P0.0",
.DIP10 = "P0.1",
.DIP11 = "P0.18",
.DIP12 = "P0.17",
.DIP13 = "P0.15",
.DIP14 = "P0.16",
.DIP15 = "P0.23",
.DIP16 = "P0.24",
.DIP17 = "P0.25",
.DIP18 = "P0.26",
.DIP19 = "P1.30",
.DIP20 = "P1.31",
.DIP21 = "P2.5",
.DIP22 = "P2.4",
.DIP23 = "P2.3",
.DIP24 = "P2.2",
.DIP25 = "P2.1",
.DIP26 = "P2.0",
.DIP27 = "P0.11",
.DIP28 = "P0.10",
.DIP29 = "P0.5",
.DIP30 = "P0.4",
};

@ -1,6 +1,18 @@
const std = @import("std"); const std = @import("std");
const microzig = @import("../deps/microzig/src/main.zig"); const micro = @import("../deps/microzig/src/main.zig");
const Chip = micro.Chip;
const MemoryRegion = micro.MemoryRegion;
fn root_dir() []const u8 { fn root_dir() []const u8 {
return std.fs.path.dirname(@src().file) orelse "."; return std.fs.path.dirname(@src().file) orelse unreachable;
} }
pub const lpc176x5x = Chip.from_standard_paths(root_dir(), .{
.name = "LPC176x5x",
.cpu = micro.cpus.cortex_m3,
.memory_regions = &.{
MemoryRegion{ .offset = 0x00000000, .length = 512 * 1024, .kind = .flash },
MemoryRegion{ .offset = 0x10000000, .length = 32 * 1024, .kind = .ram },
MemoryRegion{ .offset = 0x2007C000, .length = 32 * 1024, .kind = .ram },
},
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,205 @@
const std = @import("std");
const micro = @import("microzig");
const chip = @import("registers.zig");
const regs = chip.registers;
pub usingnamespace chip;
pub const clock = struct {
pub const Domain = enum {
cpu,
};
};
pub const clock_frequencies = .{
.cpu = 100_000_000, // 100 Mhz
};
pub const PinTarget = enum(u2) {
func00 = 0b00,
func01 = 0b01,
func10 = 0b10,
func11 = 0b11,
};
pub fn parse_pin(comptime spec: []const u8) type {
const invalid_format_msg = "The given pin '" ++ spec ++ "' has an invalid format. Pins must follow the format \"P{Port}.{Pin}\" scheme.";
if (spec[0] != 'P')
@compileError(invalid_format_msg);
const index = std.mem.indexOfScalar(u8, spec, '.') orelse @compileError(invalid_format_msg);
const _port: comptime_int = std.fmt.parseInt(u3, spec[1..index], 10) catch @compileError(invalid_format_msg);
const _pin: comptime_int = std.fmt.parseInt(u5, spec[index + 1 ..], 10) catch @compileError(invalid_format_msg);
const sel_reg_name = std.fmt.comptimePrint("PINSEL{d}", .{(2 * _port + _pin / 16)});
const _regs = struct {
const name_suffix = std.fmt.comptimePrint("{d}", .{_port});
const pinsel_reg = @field(regs.PINCONNECT, sel_reg_name);
const pinsel_field = std.fmt.comptimePrint("P{d}_{d}", .{ _port, _pin });
const dir = @field(regs.GPIO, "DIR" ++ name_suffix);
const pin = @field(regs.GPIO, "PIN" ++ name_suffix);
const set = @field(regs.GPIO, "SET" ++ name_suffix);
const clr = @field(regs.GPIO, "CLR" ++ name_suffix);
const mask = @field(regs.GPIO, "MASK" ++ name_suffix);
};
return struct {
pub const port: u3 = _port;
pub const pin: u5 = _pin;
pub const regs = _regs;
const gpio_mask: u32 = (1 << pin);
pub const Targets = PinTarget;
};
}
pub fn route_pin(comptime pin: type, function: PinTarget) void {
var val = pin.regs.pinsel_reg.read();
@field(val, pin.regs.pinsel_field) = @enumToInt(function);
pin.regs.pinsel_reg.write(val);
}
pub const gpio = struct {
pub fn set_output(comptime pin: type) void {
pin.regs.dir.raw |= pin.gpio_mask;
}
pub fn set_input(comptime pin: type) void {
pin.regs.dir.raw &= ~pin.gpio_mask;
}
pub fn read(comptime pin: type) micro.gpio.State {
return if ((pin.regs.pin.raw & pin.gpio_mask) != 0)
micro.gpio.State.high
else
micro.gpio.State.low;
}
pub fn write(comptime pin: type, state: micro.gpio.State) void {
if (state == .high) {
pin.regs.set.raw = pin.gpio_mask;
} else {
pin.regs.clr.raw = pin.gpio_mask;
}
}
};
pub const uart = struct {
pub const DataBits = enum(u2) {
five = 0,
six = 1,
seven = 2,
eight = 3,
};
pub const StopBits = enum(u1) {
one = 0,
two = 1,
};
pub const Parity = enum(u2) {
odd = 0,
even = 1,
mark = 2,
space = 3,
};
pub const CClkDiv = enum(u2) {
four = 0,
one = 1,
two = 2,
eight = 3,
};
};
pub fn Uart(comptime index: usize, comptime pins: micro.uart.Pins) type {
if (pins.tx != null or pins.rx != null)
@compileError("TODO: custom pins are not currently supported");
return struct {
const UARTn = switch (index) {
0 => regs.UART0,
1 => regs.UART1,
2 => regs.UART2,
3 => regs.UART3,
else => @compileError("LPC1768 has 4 UARTs available."),
};
const Self = @This();
pub fn init(config: micro.uart.Config) !Self {
micro.debug.write("0");
switch (index) {
0 => {
regs.SYSCON.PCONP.modify(.{ .PCUART0 = 1 });
regs.SYSCON.PCLKSEL0.modify(.{ .PCLK_UART0 = @enumToInt(uart.CClkDiv.four) });
},
1 => {
regs.SYSCON.PCONP.modify(.{ .PCUART1 = 1 });
regs.SYSCON.PCLKSEL0.modify(.{ .PCLK_UART1 = @enumToInt(uart.CClkDiv.four) });
},
2 => {
regs.SYSCON.PCONP.modify(.{ .PCUART2 = 1 });
regs.SYSCON.PCLKSEL1.modify(.{ .PCLK_UART2 = @enumToInt(uart.CClkDiv.four) });
},
3 => {
regs.SYSCON.PCONP.modify(.{ .PCUART3 = 1 });
regs.SYSCON.PCLKSEL1.modify(.{ .PCLK_UART3 = @enumToInt(uart.CClkDiv.four) });
},
else => unreachable,
}
micro.debug.write("1");
UARTn.LCR.modify(.{
// 8N1
.WLS = @enumToInt(config.data_bits),
.SBS = @enumToInt(config.stop_bits),
.PE = if (config.parity != null) @as(u1, 1) else @as(u1, 0),
.PS = if (config.parity) |p| @enumToInt(p) else @enumToInt(uart.Parity.odd),
.BC = 0,
.DLAB = 1,
});
micro.debug.write("2");
// TODO: UARTN_FIFOS_ARE_DISA is not available in all uarts
//UARTn.FCR.modify(.{ .FIFOEN = .UARTN_FIFOS_ARE_DISA });
micro.debug.writer().print("clock: {} baud: {} ", .{
micro.clock.get().cpu,
config.baud_rate,
}) catch {};
const pclk = micro.clock.get().cpu / 4;
const divider = (pclk / (16 * config.baud_rate));
const regval = std.math.cast(u16, divider) orelse return error.UnsupportedBaudRate;
UARTn.DLL.modify(.{ .DLLSB = @truncate(u8, regval >> 0x00) });
UARTn.DLM.modify(.{ .DLMSB = @truncate(u8, regval >> 0x08) });
UARTn.LCR.modify(.{ .DLAB = 0 });
return Self{};
}
pub fn can_write(self: Self) bool {
_ = self;
return (UARTn.LSR.read().THRE == 1);
}
pub fn tx(self: Self, ch: u8) void {
while (!self.can_write()) {} // Wait for Previous transmission
UARTn.THR.raw = ch; // Load the data to be transmitted
}
pub fn can_read(self: Self) bool {
_ = self;
return (UARTn.LSR.read().RDR == 1);
}
pub fn rx(self: Self) u8 {
while (!self.can_read()) {} // Wait till the data is received
return UARTn.RBR.read().RBR; // Read received data
}
};
}
Loading…
Cancel
Save