add chips and boards (#1)

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

@ -1,4 +1,4 @@
steps: steps:
- group: Build - group: Build
steps: steps:
- command: zig build - command: zig build -Doptimize=ReleaseSmall

@ -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,18 @@
= Hardware Support Package Template = Microchip ATmega Hardware Support Package
1. Update LICENSE file Note: for testing, renode supports arduino nano 33 BLE
2. Update `microzig` submodule under `deps/`
3. Add chips/boards/hals Currently LLVM is having trouble lowering AVR when this is built in debug mode:
4. Set up buildkite pipeline
[source]
----
LLVM Emit Object... Don't know how to custom lower this!
UNREACHABLE executed at /Users/mattnite/code/llvm-project-15/llvm/lib/Target/AVR/AVRISelLowering.cpp:842!
----
for now always build in release small:
[source]
----
zig build -Doptimize=ReleaseSmall
----

2
deps/microzig vendored

@ -1 +1 @@
Subproject commit 97ca5497da0f22d025e18bced9311efed088d893 Subproject commit 2d0ee5c4731de1d81afb9c8e08ba4e8c2c2cfbf3

@ -1,6 +1,19 @@
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 unreachable;
} }
pub const arduino_nano = micro.Board{
.name = "Arduino Nano",
.source = .{ .path = root_dir() ++ "/boards/arduino_nano.zig" },
.chip = chips.atmega328p,
};
pub const arduino_uno = micro.Board{
.name = "Arduino Uno",
.source = .{ .path = root_dir() ++ "/boards/arduino_uno.zig" },
.chip = chips.atmega328p,
};

@ -0,0 +1,33 @@
pub const chip = @import("chip");
pub const clock_frequencies = .{
.cpu = 16_000_000,
};
pub const pin_map = .{
// Port A
.D0 = "PD0",
.D1 = "PD1",
.D2 = "PD2",
.D3 = "PD3",
.D4 = "PD4",
.D5 = "PD5",
.D6 = "PD6",
.D7 = "PD7",
// Port B
.D8 = "PB0",
.D9 = "PB1",
.D10 = "PB2",
.D11 = "PB3",
.D12 = "PB4",
.D13 = "PB5",
// Port C (Analog)
.A0 = "PC0",
.A1 = "PC1",
.A2 = "PC2",
.A3 = "PC3",
.A4 = "PC4",
.A5 = "PC5",
.A6 = "ADC6",
.A7 = "ADC7",
};

@ -0,0 +1,32 @@
pub const chip = @import("chip");
pub const clock_frequencies = .{
.cpu = 16_000_000,
};
pub const pin_map = .{
// Port D
.D0 = "PD0",
.D1 = "PD1",
.D2 = "PD2",
.D3 = "PD3",
.D4 = "PD4",
.D5 = "PD5",
.D6 = "PD6",
.D7 = "PD7",
// Port B
.D8 = "PB0",
.D9 = "PB1",
.D10 = "PB2",
.D11 = "PB3",
.D12 = "PB4",
// LED_BUILTIN
.D13 = "PB5",
// Port C (Analog)
.A0 = "PC0",
.A1 = "PC1",
.A2 = "PC2",
.A3 = "PC3",
.A4 = "PC4",
.A5 = "PC5",
};

@ -1,6 +1,17 @@
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 ".";
} }
pub const atmega328p = Chip.from_standard_paths(root_dir(), .{
.name = "ATmega328P",
.cpu = micro.cpus.avr5,
.memory_regions = &.{
MemoryRegion{ .offset = 0x000000, .length = 32 * 1024, .kind = .flash },
MemoryRegion{ .offset = 0x800100, .length = 2048, .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,191 @@
const std = @import("std");
const micro = @import("microzig");
pub usingnamespace @import("registers.zig");
const regz = @import("registers.zig").registers;
pub const cpu = micro.cpu;
const Port = enum(u8) {
B = 1,
C = 2,
D = 3,
};
pub const clock = struct {
pub const Domain = enum {
cpu,
};
};
pub fn parsePin(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.len != 3)
@compileError(invalid_format_msg);
if (spec[0] != 'P')
@compileError(invalid_format_msg);
return struct {
pub const port: Port = std.meta.stringToEnum(Port, spec[1..2]) orelse @compileError(invalid_format_msg);
pub const pin: u3 = std.fmt.parseInt(u3, spec[2..3], 10) catch @compileError(invalid_format_msg);
};
}
pub const gpio = struct {
fn regs(comptime desc: type) type {
return struct {
// io address
const pin_addr: u5 = 3 * @enumToInt(desc.port) + 0x00;
const dir_addr: u5 = 3 * @enumToInt(desc.port) + 0x01;
const port_addr: u5 = 3 * @enumToInt(desc.port) + 0x02;
// ram mapping
const pin = @intToPtr(*volatile u8, 0x20 + @as(usize, pin_addr));
const dir = @intToPtr(*volatile u8, 0x20 + @as(usize, dir_addr));
const port = @intToPtr(*volatile u8, 0x20 + @as(usize, port_addr));
};
}
pub fn setOutput(comptime pin: type) void {
cpu.sbi(regs(pin).dir_addr, pin.pin);
}
pub fn setInput(comptime pin: type) void {
cpu.cbi(regs(pin).dir_addr, pin.pin);
}
pub fn read(comptime pin: type) micro.gpio.State {
return if ((regs(pin).pin.* & (1 << pin.pin)) != 0)
.high
else
.low;
}
pub fn write(comptime pin: type, state: micro.gpio.State) void {
if (state == .high) {
cpu.sbi(regs(pin).port_addr, pin.pin);
} else {
cpu.cbi(regs(pin).port_addr, pin.pin);
}
}
pub fn toggle(comptime pin: type) void {
cpu.sbi(regs(pin).pin_addr, pin.pin);
}
};
pub const uart = struct {
pub const DataBits = enum {
five,
six,
seven,
eight,
nine,
};
pub const StopBits = enum {
one,
two,
};
pub const Parity = enum {
odd,
even,
};
};
pub fn Uart(comptime index: usize, comptime pins: micro.uart.Pins) type {
if (index != 0) @compileError("Atmega328p only has a single uart!");
if (pins.tx != null or pins.rx != null)
@compileError("Atmega328p has fixed pins for uart!");
return struct {
const Self = @This();
fn computeDivider(baud_rate: u32) !u12 {
const pclk = micro.clock.get().cpu;
const divider = ((pclk + (8 * baud_rate)) / (16 * baud_rate)) - 1;
return std.math.cast(u12, divider) orelse return error.UnsupportedBaudRate;
}
fn computeBaudRate(divider: u12) u32 {
return micro.clock.get().cpu / (16 * @as(u32, divider) + 1);
}
pub fn init(config: micro.uart.Config) !Self {
const ucsz: u3 = switch (config.data_bits) {
.five => 0b000,
.six => 0b001,
.seven => 0b010,
.eight => 0b011,
.nine => return error.UnsupportedWordSize, // 0b111
};
const upm: u2 = if (config.parity) |parity| switch (parity) {
.even => @as(u2, 0b10), // even
.odd => @as(u2, 0b11), // odd
} else 0b00; // parity disabled
const usbs: u1 = switch (config.stop_bits) {
.one => 0b0,
.two => 0b1,
};
const umsel: u2 = 0b00; // Asynchronous USART
// baud is computed like this:
// f(osc)
// BAUD = ----------------
// 16 * (UBRRn + 1)
const ubrr_val = try computeDivider(config.baud_rate);
regz.USART0.UCSR0A.modify(.{
.MPCM0 = 0,
.U2X0 = 0,
});
regz.USART0.UCSR0B.write(.{
.TXB80 = 0, // we don't care about these btw
.RXB80 = 0, // we don't care about these btw
.UCSZ02 = @truncate(u1, (ucsz & 0x04) >> 2),
.TXEN0 = 1,
.RXEN0 = 1,
.UDRIE0 = 0, // no interrupts
.TXCIE0 = 0, // no interrupts
.RXCIE0 = 0, // no interrupts
});
regz.USART0.UCSR0C.write(.{
.UCPOL0 = 0, // async mode
.UCSZ0 = @truncate(u2, (ucsz & 0x03) >> 0),
.USBS0 = usbs,
.UPM0 = upm,
.UMSEL0 = umsel,
});
regz.USART0.UBRR0.modify(ubrr_val);
return Self{};
}
pub fn canWrite(self: Self) bool {
_ = self;
return (regz.USART0.UCSR0A.read().UDRE0 == 1);
}
pub fn tx(self: Self, ch: u8) void {
while (!self.canWrite()) {} // Wait for Previous transmission
regz.USART0.UDR0.* = ch; // Load the data to be transmitted
}
pub fn canRead(self: Self) bool {
_ = self;
return (regz.USART0.UCSR0A.read().RXC0 == 1);
}
pub fn rx(self: Self) u8 {
while (!self.canRead()) {} // Wait till the data is received
return regz.USART0.UDR0.*; // Read received data
}
};
}
Loading…
Cancel
Save