Avr fixes (#36)

* Makes AVR UART work.

Co-authored-by: Felix "xq" Queißner <git@masterq32.de>
wch-ch32v003
Felix Queißner 3 years ago committed by GitHub
parent 97733da9e2
commit d3c539e35b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,6 +1,8 @@
const std = @import("std"); const std = @import("std");
const micro = @import("microzig"); const micro = @import("microzig");
pub usingnamespace @import("registers.zig"); pub usingnamespace @import("registers.zig");
const regz = @import("registers.zig").registers;
pub const cpu = micro.cpu; pub const cpu = micro.cpu;
const Port = enum(u8) { const Port = enum(u8) {
@ -26,13 +28,15 @@ pub fn parsePin(comptime spec: []const u8) type {
pub const gpio = struct { pub const gpio = struct {
fn regs(comptime desc: type) type { fn regs(comptime desc: type) type {
return struct { return struct {
const pin_addr = 3 * @enumToInt(desc.port) + 0x00; // io address
const dir_addr = 3 * @enumToInt(desc.port) + 0x01; const pin_addr: u5 = 3 * @enumToInt(desc.port) + 0x00;
const port_addr = 3 * @enumToInt(desc.port) + 0x02; const dir_addr: u5 = 3 * @enumToInt(desc.port) + 0x01;
const port_addr: u5 = 3 * @enumToInt(desc.port) + 0x02;
const pin = @intToPtr(*volatile u8, pin_addr); // ram mapping
const dir = @intToPtr(*volatile u8, dir_addr); const pin = @intToPtr(*volatile u8, 0x20 + @as(usize, pin_addr));
const port = @intToPtr(*volatile u8, port_addr); const dir = @intToPtr(*volatile u8, 0x20 + @as(usize, dir_addr));
const port = @intToPtr(*volatile u8, 0x20 + @as(usize, port_addr));
}; };
} }
@ -63,3 +67,116 @@ pub const gpio = struct {
cpu.sbi(regs(pin).pin_addr, pin.pin); 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) type {
if (index != 0) @compileError("Atmega328p only has a single uart!");
return struct {
const Self = @This();
fn computeDivider(baud_rate: u32) !u12 {
const pclk = micro.clock.get();
const divider = ((pclk + (8 * baud_rate)) / (16 * baud_rate)) - 1;
return std.math.cast(u12, divider) catch return error.UnsupportedBaudRate;
}
fn computeBaudRate(divider: u12) u32 {
return micro.clock.get() / (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
}
};
}

@ -279,7 +279,7 @@ pub const registers = struct {
/// address: 0xc4 /// address: 0xc4
/// USART Baud Rate Register Bytes /// USART Baud Rate Register Bytes
pub const UBRR0 = @intToPtr(*volatile u12, 0xc4); pub const UBRR0 = @intToPtr(*volatile MmioInt(16, u12), 0xc4);
}; };
/// Two Wire Serial Interface /// Two Wire Serial Interface
@ -1110,7 +1110,7 @@ pub const registers = struct {
/// address: 0x5d /// address: 0x5d
/// Stack Pointer /// Stack Pointer
pub const SP = @intToPtr(*volatile u12, 0x5d); pub const SP = @intToPtr(*volatile MmioInt(16, u12), 0x5d);
/// address: 0x57 /// address: 0x57
/// Store Program Memory Control and Status Register /// Store Program Memory Control and Status Register

Loading…
Cancel
Save