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
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
2. Update `microzig` submodule under `deps/`
3. Add chips/boards/hals
4. Set up buildkite pipeline
Please see https://github.com/ZigEmbeddedGroup/lpcboot[lpcboot] as well

@ -1,6 +1,13 @@
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 {
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 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 {
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