mbed LPC1768 only commit. This introduces a working UART abstraction for LPC1768, currently the uart-sync example has chip-related code in it.

wch-ch32v003
Felix (xq) Queißner 3 years ago
parent 294cfebf7a
commit 196c4c4d05

@ -185,7 +185,7 @@ fn addEmbeddedExecutable(builder: *std.build.Builder, name: []const u8, source:
// - This requires building another tool that runs on the host that compiles those files and emits the linker script.
// - src/tools/linkerscript-gen.zig is the source file for this
exe.bundle_compiler_rt = false;
// exe.bundle_compiler_rt = false;
switch (backing) {
.chip => {

@ -0,0 +1,38 @@
const std = @import("std");
const micro = @import("microzig.zig");
pub fn busySleep(comptime limit: comptime_int) void {
if (limit <= 0) @compileError("limit must be non-negative!");
comptime var bits = 0;
inline while ((1 << bits) <= limit) {
bits += 1;
}
const I = std.meta.Int(.unsigned, bits);
var i: I = 0;
while (i < limit) : (i += 1) {
@import("std").mem.doNotOptimizeAway(i);
}
}
const DebugErr = error{};
fn writerWrite(ctx: void, string: []const u8) DebugErr!usize {
write(string);
return string.len;
}
const DebugWriter = std.io.Writer(void, DebugErr, writerWrite);
pub fn write(string: []const u8) void {
if (!micro.config.has_board)
return;
if (!@hasDecl(micro.board, "debugWrite"))
return;
micro.board.debugWrite(string);
}
pub fn writer() DebugWriter {
return DebugWriter{ .context = {} };
}

@ -57,12 +57,12 @@ pub fn Gpio(comptime pin: type, config: anytype) type {
}
fn read() State {
return @intToEnum(State, chip.gpio.read(pin.source_pin));
return chip.gpio.read(pin.source_pin);
}
// outputs:
fn write(state: State) void {
chip.gpio.write(pin.source_pin, @enumToInt(state));
chip.gpio.write(pin.source_pin, state);
}
fn setToHigh() void {

@ -30,13 +30,29 @@ pub const Pin = pin.Pin;
pub const uart = @import("uart.zig");
pub const Uart = uart.Uart;
pub const debug = @import("debug.zig");
/// The microzig panic handler. Will disable interrupts and loop endlessly.
/// Export this symbol from your main file to enable microzig:
/// ```
/// const micro = @import("microzig");
/// pub const panic = micro.panic;
/// ```
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
pub fn panic(message: []const u8, maybe_stack_trace: ?*std.builtin.StackTrace) noreturn {
var writer = debug.writer();
writer.print("microzig PANIC: {s}\r\n", .{message}) catch unreachable;
if (maybe_stack_trace) |stack_trace| {
var frame_index: usize = 0;
var frames_left: usize = std.math.min(stack_trace.index, stack_trace.instruction_addresses.len);
while (frames_left != 0) : ({
frames_left -= 1;
frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;
}) {
const return_address = stack_trace.instruction_addresses[frame_index];
writer.print("0x{X:0>8}\r\n", .{return_address}) catch unreachable;
}
}
hang();
}

@ -24,11 +24,14 @@ pub fn MMIO(comptime size: u8, comptime PackedT: type) type {
pub const underlying_type = PackedT;
pub fn read(addr: *volatile Self) PackedT {
return @bitCast(PackedT, addr.*);
return @bitCast(PackedT, addr.raw);
}
pub fn write(addr: *volatile Self, val: PackedT) void {
addr.* = @bitCast(IntT, val);
// This is a workaround for a compiler bug related to miscompilation
// If the tmp var is not used, result location will fuck things up
var tmp = @bitCast(IntT, val);
addr.raw = tmp;
}
pub fn modify(addr: *volatile Self, fields: anytype) void {

@ -28,7 +28,7 @@ pub fn Pin(comptime spec: []const u8) type {
pub const source_pin = pin;
pub fn route(target: pin.Targets) void {
unreachable;
chip.routePin(source_pin, target);
}
};
}

@ -1,4 +1,35 @@
pub const chip = @import("chip");
pub const micro = @import("microzig");
pub fn debugWrite(string: []const u8) void {
const clk_pin = micro.Pin("DIP5");
const dat_pin = micro.Pin("DIP6");
const clk = micro.Gpio(clk_pin, .{ .mode = .output, .initial_state = .low });
const dat = micro.Gpio(dat_pin, .{ .mode = .output, .initial_state = .low });
clk.init();
dat.init();
micro.debug.busySleep(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.busySleep(1_000);
clk.write(.low);
micro.debug.busySleep(1_000);
}
}
dat.write(.low);
clk.write(.low);
}
pub const pin_map = .{
// Onboard-LEDs

@ -11,6 +11,13 @@ pub const memory_regions = [_]micro_linker.MemoryRegion{
micro_linker.MemoryRegion{ .offset = 0x2007C000, .length = 32 * 1024, .kind = .ram },
};
pub const PinTarget = enum(u2) {
func00 = 0b00,
func01 = 0b01,
func10 = 0b10,
func11 = 0b11,
};
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[0] != 'P')
@ -18,12 +25,17 @@ pub fn parsePin(comptime spec: []const u8) type {
const index = std.mem.indexOfScalar(u8, spec, '.') orelse @compileError(invalid_format_msg);
const _port: u3 = std.fmt.parseInt(u3, spec[1..index], 10) catch @compileError(invalid_format_msg);
const _pin: u5 = std.fmt.parseInt(u5, spec[index + 1 ..], 10) catch @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(registers.PINCONNECT, sel_reg_name);
const pinsel_field = std.fmt.comptimePrint("P{d}_{d}", .{ _port, _pin });
const dir = @field(registers.GPIO, "DIR" ++ name_suffix);
const pin = @field(registers.GPIO, "PIN" ++ name_suffix);
const set = @field(registers.GPIO, "SET" ++ name_suffix);
@ -32,13 +44,21 @@ pub fn parsePin(comptime spec: []const u8) type {
};
return struct {
pub const port = _port;
pub const pin = _pin;
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 routePin(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 setOutput(comptime pin: type) void {
pin.regs.dir.raw |= pin.gpio_mask;
@ -47,15 +67,15 @@ pub const gpio = struct {
pin.regs.dir.raw &= ~pin.gpio_mask;
}
pub fn read(comptime pin: type) u1 {
pub fn read(comptime pin: type) micro.gpio.State {
return if ((pin.regs.pin.raw & pin.gpio_mask) != 0)
@as(u1, 1)
micro.gpio.State.high
else
0;
micro.gpio.State.low;
}
pub fn write(comptime pin: type, state: u1) void {
if (state == 1) {
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;
@ -75,6 +95,7 @@ pub fn Uart(comptime index: usize) type {
const Self = @This();
pub fn init(config: micro.uart.Config) !Self {
micro.debug.write("0");
switch (index) {
0 => {
registers.SYSCON.PCONP.modify(.{ .PCUART0 = true });
@ -94,6 +115,7 @@ pub fn Uart(comptime index: usize) type {
},
else => unreachable,
}
micro.debug.write("1");
UARTn.LCR.write(.{
// 8N1
@ -118,8 +140,14 @@ pub fn Uart(comptime index: usize) type {
.BC = false,
.DLAB = true,
});
micro.debug.write("2");
UARTn.FCR.modify(.{ .FIFOEN = false });
micro.debug.writer().print("clock: {} baud: {} ", .{
micro.clock.get(),
config.baud_rate,
}) catch {};
const pclk = micro.clock.get() / 4;
const divider = (pclk / (16 * config.baud_rate));

@ -1,49 +1,42 @@
const std = @import("std");
pub fn sei() void {
__enable_irq();
asm volatile ("cpsie i");
}
pub fn cli() void {
__disable_irq();
}
pub fn __enable_irq() void {
asm volatile ("cpsie i");
}
pub fn __disable_irq() void {
asm volatile ("cpsid i");
}
pub fn __enable_fault_irq() void {
pub fn enable_fault_irq() void {
asm volatile ("cpsie f");
}
pub fn __disable_fault_irq() void {
pub fn disable_fault_irq() void {
asm volatile ("cpsid f");
}
pub fn __NOP() void {
pub fn nop() void {
asm volatile ("nop");
}
pub fn __WFI() void {
pub fn wfi() void {
asm volatile ("wfi");
}
pub fn __WFE() void {
pub fn wfe() void {
asm volatile ("wfe");
}
pub fn __SEV() void {
pub fn sev() void {
asm volatile ("sev");
}
pub fn __ISB() void {
pub fn isb() void {
asm volatile ("isb");
}
pub fn __DSB() void {
pub fn dsb() void {
asm volatile ("dsb");
}
pub fn __DMB() void {
pub fn dmb() void {
asm volatile ("dmb");
}
pub fn __CLREX() void {
pub fn clrex() void {
asm volatile ("clrex");
}
@ -53,11 +46,11 @@ pub const startup_logic = struct {
const VectorTable = extern struct {
initial_stack_pointer: u32,
reset: InterruptVector,
nmi: InterruptVector = unhandledInterrupt,
hard_fault: InterruptVector = unhandledInterrupt,
mpu_fault: InterruptVector = unhandledInterrupt,
bus_fault: InterruptVector = unhandledInterrupt,
usage_fault: InterruptVector = unhandledInterrupt,
nmi: InterruptVector = makeUnhandledHandler("nmi"),
hard_fault: InterruptVector = makeUnhandledHandler("hard_fault"),
mpu_fault: InterruptVector = makeUnhandledHandler("mpu_fault"),
bus_fault: InterruptVector = makeUnhandledHandler("bus_fault"),
usage_fault: InterruptVector = makeUnhandledHandler("usage_fault"),
reserved: u32 = 0,
};
@ -68,8 +61,12 @@ pub const startup_logic = struct {
.reset = _start,
};
fn makeUnhandledHandler(comptime str: []const u8) fn () callconv(.C) noreturn {
return struct {
fn unhandledInterrupt() callconv(.C) noreturn {
@panic("unhandled interrupt");
@panic("unhandled interrupt: " ++ str);
}
}.unhandledInterrupt;
}
extern fn microzig_main() noreturn;

@ -7,25 +7,116 @@ pub const panic = micro.panic;
const uart_txd_pin = micro.Pin("P0.15");
const uart_rxd_pin = micro.Pin("P0.16");
pub const cpu_frequency: u32 = 10_000_000; // 10 MHz
const debug_pin = micro.Pin("P0.17");
const led1_pin = micro.Pin("P1.18");
const led2_pin = micro.Pin("P1.20");
const led3_pin = micro.Pin("P1.21");
const led4_pin = micro.Pin("P1.23");
pub const cpu_frequency: u32 = 100_000_000; // 100 MHz
const PLL = struct {
fn init() void {
reset_overclocking();
}
fn reset_overclocking() void {
overclock_flash(5); // 5 cycles access time
overclock_pll(3); // 100 MHz
}
fn overclock_flash(timing: u5) void {
micro.chip.registers.SYSCON.FLASHCFG.write(.{
.FLASHTIM = @intCast(u4, timing - 1),
});
}
fn feed_pll() callconv(.Inline) void {
micro.chip.registers.SYSCON.PLL0FEED.write(.{ .PLL0FEED = 0xAA });
micro.chip.registers.SYSCON.PLL0FEED.write(.{ .PLL0FEED = 0x55 });
}
fn overclock_pll(divider: u8) void {
// PLL einrichten für RC
micro.chip.registers.SYSCON.PLL0CON.write(.{
.PLLE0 = false,
.PLLC0 = false,
});
feed_pll();
micro.chip.registers.SYSCON.CLKSRCSEL.write(.{ .CLKSRC = 0 }); // RC-Oszillator als Quelle
micro.chip.registers.SYSCON.PLL0CFG.write(.{
// SysClk = (4MHz / 2) * (2 * 75) = 300 MHz
.MSEL0 = 74,
.NSEL0 = 1,
});
// CPU Takt = SysClk / divider
micro.chip.registers.SYSCON.CCLKCFG.write(.{ .CCLKSEL = divider - 1 });
feed_pll();
micro.chip.registers.SYSCON.PLL0CON.modify(.{ .PLLE0 = true }); // PLL einschalten
feed_pll();
var i: usize = 0;
while (i < 1_000) : (i += 1) {
micro.cpu.nop();
}
micro.chip.registers.SYSCON.PLL0CON.modify(.{ .PLLC0 = true });
feed_pll();
}
};
pub fn main() !void {
var debug_port = try micro.Uart(0).init(.{
const gpio_init = .{ .mode = .output, .initial_state = .low };
const led1 = micro.Gpio(led1_pin, gpio_init);
const led2 = micro.Gpio(led2_pin, gpio_init);
const led3 = micro.Gpio(led3_pin, gpio_init);
const led4 = micro.Gpio(led4_pin, gpio_init);
const status = micro.Gpio(debug_pin, .{
.mode = .output,
.initial_state = .high,
});
status.init();
led1.init();
led2.init();
led3.init();
led4.init();
uart_txd_pin.route(.func01);
uart_rxd_pin.route(.func01);
PLL.init();
led1.setToHigh();
var debug_port = micro.Uart(1).init(.{
.baud_rate = 9600,
.stop_bits = .one,
.parity = .none, // { none, even, odd, mark, space }
.data_bits = .@"8", // 5, 6, 7, 8, or 9 data bits
});
}) catch |err| {
led1.write(if (err == error.UnsupportedBaudRate) micro.gpio.State.low else .high);
led2.write(if (err == error.UnsupportedParity) micro.gpio.State.low else .high);
led3.write(if (err == error.UnsupportedStopBitCount) micro.gpio.State.low else .high);
led4.write(if (err == error.UnsupportedWordSize) micro.gpio.State.low else .high);
micro.hang();
};
led2.setToHigh();
var out = debug_port.writer();
var in = debug_port.reader();
try out.writeAll("Please enter a sentence:\r\n");
led3.setToHigh();
while (true) {
try out.writeAll("> ");
var line_buffer: [64]u8 = undefined;
const line = (try in.readUntilDelimiterOrEof(&line_buffer, '\r')).?;
try out.writeAll(line);
try out.writeAll(".");
led4.toggle();
micro.debug.busySleep(100_000);
}
}

Loading…
Cancel
Save