diff --git a/build.zig b/build.zig index 3f49cf7..c0d71db 100644 --- a/build.zig +++ b/build.zig @@ -34,7 +34,7 @@ pub fn build(b: *std.build.Builder) void { "esp-bringup", "src/example/blinky.zig", .{ .chip = esp32_c3 }, - .{}, + .{ .hal_package_path = .{ .path = "src/hal/root.zig" } }, ); exe.setBuildMode(mode); exe.install(); diff --git a/perform-flash.sh b/perform-flash.sh new file mode 100755 index 0000000..ce1f5de --- /dev/null +++ b/perform-flash.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e + +clear +zig build -Drelease-small +llvm-objdump -S ./zig-out/bin/esp-bringup > /tmp/dump.txt +esptool.py \ + --port /dev/ttyUSB0 \ + --baud 115200 \ + write_flash 0x00000000 zig-out/bin/firmware.bin \ + --verify +picocom --baud 115200 /dev/ttyUSB0 \ No newline at end of file diff --git a/src/example/blinky.zig b/src/example/blinky.zig index 6bba15b..0518c53 100644 --- a/src/example/blinky.zig +++ b/src/example/blinky.zig @@ -1,29 +1,52 @@ const std = @import("std"); const microzig = @import("microzig"); +const dogfood: u32 = 0x50D83AA1; +const super_dogfood: u32 = 0x8F1D312A; + pub fn main() !void { - // const led_r_mux = @ptrToInt(*volatile u32, IO_MUX_BASE + IO_MUX_GPIOn_REG(LED_R_PIN)); - // const led_g_mux = @ptrToInt(*volatile u32, IO_MUX_BASE + IO_MUX_GPIOn_REG(LED_G_PIN)); - // const led_b_mux = @ptrToInt(*volatile u32, IO_MUX_BASE + IO_MUX_GPIOn_REG(LED_B_PIN)); + microzig.chip.registers.TIMG0.WDTWPROTECT.raw = dogfood; + microzig.chip.registers.TIMG0.WDTCONFIG0.raw = 0; + microzig.chip.registers.TIMG0.WDTWPROTECT.raw = 0; - // led_r_mux.* = 0x80; + microzig.chip.registers.RTC_CNTL.WDTWPROTECT.raw = dogfood; + microzig.chip.registers.RTC_CNTL.WDTCONFIG0.raw = 0; + microzig.chip.registers.RTC_CNTL.WDTWPROTECT.raw = 0; - const gpio_out = @intToPtr(*volatile u32, GPIO_BASE + GPIO_OUT_REG); - const gpio_ena = @intToPtr(*volatile u32, GPIO_BASE + GPIO_ENABLE_REG); - gpio_ena.* = (1 << LED_R_PIN) | (1 << LED_G_PIN) | (1 << LED_B_PIN); - gpio_out.* = (1 << LED_R_PIN) | (1 << LED_G_PIN) | (1 << LED_B_PIN); -} + microzig.chip.registers.RTC_CNTL.SWD_WPROTECT.raw = super_dogfood; + microzig.chip.registers.RTC_CNTL.SWD_CONF.modify(.{ .SWD_DISABLE = 1 }); + microzig.chip.registers.RTC_CNTL.SWD_WPROTECT.raw = 0; + + microzig.chip.registers.INTERRUPT_CORE0.CPU_INT_ENABLE.* = 0; -const GPIO_BASE = 0x6000_4000; -const IO_MUX_BASE = 0x6000_9000; + microzig.hal.gpio.init(LED_R_PIN, .{ + .direction = .output, + .direct_io = true, + }); + microzig.hal.gpio.init(LED_G_PIN, .{ + .direction = .output, + .direct_io = true, + }); + microzig.hal.gpio.init(LED_B_PIN, .{ + .direction = .output, + .direct_io = true, + }); -const GPIO_OUT_REG = 0x0004; -const GPIO_ENABLE_REG = 0x0020; + microzig.hal.uart.write(0, "Hello from Zig!\r\n"); -fn GPIO_FUNCn_OUT_SEL_CFG_REG(comptime n: comptime_int) comptime_int { - return 0x0554 + 4 * n; + while (true) { + microzig.chip.registers.GPIO.OUT.modify(.{ .DATA_ORIG = (1 << LED_R_PIN) }); + microzig.hal.uart.write(0, "R"); + microzig.debug.busySleep(1_000_000); + microzig.chip.registers.GPIO.OUT.modify(.{ .DATA_ORIG = (1 << LED_G_PIN) }); + microzig.hal.uart.write(0, "G"); + microzig.debug.busySleep(1_000_000); + microzig.chip.registers.GPIO.OUT.modify(.{ .DATA_ORIG = (1 << LED_B_PIN) }); + microzig.hal.uart.write(0, "B"); + microzig.debug.busySleep(1_000_000); + } } -const LED_R_PIN = 3; -const LED_G_PIN = 4; -const LED_B_PIN = 5; +const LED_R_PIN = 3; // GPIO +const LED_G_PIN = 16; // GPIO +const LED_B_PIN = 17; // GPIO diff --git a/src/hal/root.zig b/src/hal/root.zig new file mode 100644 index 0000000..d87dab8 --- /dev/null +++ b/src/hal/root.zig @@ -0,0 +1,54 @@ +const std = @import("std"); +const microzig = @import("microzig"); +const regz = microzig.chip.registers; + +pub const gpio = struct { + fn getRegNamed(comptime fld: []const u8) @TypeOf(@field(regz.GPIO, fld)) { + return @field(regz.GPIO, fld); + } + + fn getReg(comptime template: []const u8, comptime pin: comptime_int) @TypeOf(@field(regz.GPIO, std.fmt.comptimePrint(template, .{pin}))) { + return getRegNamed(comptime std.fmt.comptimePrint(template, .{pin})); + } + + fn assertRange(comptime p: comptime_int) void { + if (p < 0 or p >= 21) + @compileError(std.fmt.comptimePrint("GPIO {} does not exist. GPIO pins can be between 0 and 21", .{p})); + } + + pub const Config = struct { + function: u8 = 0x80, + invert_function: bool = false, + direction: microzig.gpio.Direction, + direct_io: bool = false, + invert_direct_io: bool = false, + }; + + pub fn init(comptime pin: comptime_int, comptime config: Config) void { + assertRange(pin); + getReg("FUNC{}_OUT_SEL_CFG", pin).modify(.{ + .OUT_SEL = config.function, + .INV_SEL = @boolToInt(config.invert_function), + .OEN_SEL = @boolToInt(config.direct_io), + .OEN_INV_SEL = @boolToInt(config.invert_direct_io), + }); + switch (config.direction) { + .input => microzig.chip.registers.GPIO.ENABLE.raw &= ~(@as(u32, 1) << pin), + .output => microzig.chip.registers.GPIO.ENABLE.raw |= (@as(u32, 1) << pin), + } + } +}; + +pub const uart = struct { + fn reg(comptime index: comptime_int) @TypeOf(@field(regz, std.fmt.comptimePrint("UART{}", .{index}))) { + return @field(regz, std.fmt.comptimePrint("UART{}", .{index})); + } + + pub fn write(comptime index: comptime_int, slice: []const u8) void { + const r = reg(index); + for (slice) |c| { + while (r.STATUS.read().TXFIFO_CNT > 8) {} + r.FIFO.raw = c; + } + } +}; diff --git a/src/package/esp32-c3.zig b/src/package/esp32-c3.zig index 0a0f4fe..0ab4944 100644 --- a/src/package/esp32-c3.zig +++ b/src/package/esp32-c3.zig @@ -1,6 +1,8 @@ const std = @import("std"); const microzig = @import("microzig"); +pub const registers = @import("registers.zig").registers; + pub const startup_logic = struct { comptime { // See this: @@ -14,8 +16,6 @@ pub const startup_logic = struct { // access). The bootloader then jumps to address 0x42000008, i.e. to the // instruction at offset 8 in flash, immediately after the magic numbers. - asm (std.fmt.comptimePrint(".equ MICROZIG_INITIAL_STACK, {}", .{microzig.config.end_of_stack})); - asm ( \\.extern _start \\.section microzig_flash_start @@ -27,14 +27,14 @@ pub const startup_logic = struct { extern fn microzig_main() noreturn; - export fn _start() linksection("microzig_flash_start") callconv(.C) noreturn { - asm volatile ( - \\li sp, MICROZIG_INITIAL_STACK - \\lui a0, %%hi(_rv32_trap) - \\addi a0, a0, %%lo(_rv32_trap) - \\sw t0, 0x305(zero) + export fn _start() linksection("microzig_flash_start") callconv(.Naked) noreturn { + microzig.cpu.cli(); + asm volatile ("mv sp, %[eos]" + : + : [eos] "r" (@as(u32, microzig.config.end_of_stack)), ); - + asm volatile ("la gp, __global_pointer$"); + microzig.cpu.setStatusBit(.mtvec, microzig.config.end_of_stack); microzig.initializeSystemMemories(); microzig_main(); } @@ -42,4 +42,28 @@ pub const startup_logic = struct { export fn _rv32_trap() callconv(.C) noreturn { while (true) {} } + + const vector_table = [_]fn () callconv(.C) noreturn{ + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + _rv32_trap, + }; }; diff --git a/src/package/espressif-riscv.zig b/src/package/espressif-riscv.zig index 34dbffd..06d7bc4 100644 --- a/src/package/espressif-riscv.zig +++ b/src/package/espressif-riscv.zig @@ -1,12 +1,39 @@ const std = @import("std"); const microzig = @import("microzig"); +pub const StatusRegister = enum(u8) { + // machine information + mvendorid, + marchid, + mimpid, + mhartid, + + // machine trap setup + mstatus, + misa, + mtvec, +}; + +pub inline fn setStatusBit(comptime reg: StatusRegister, bits: u32) void { + asm volatile ("csrrs zero, " ++ @tagName(reg) ++ ", %[value]" + : + : [value] "r" (bits), + ); +} + +pub inline fn clearStatusBit(comptime reg: StatusRegister, bits: u32) void { + asm volatile ("csrrc zero, " ++ @tagName(reg) ++ ", %[value]" + : + : [value] "r" (bits), + ); +} + pub inline fn cli() void { - asm volatile (""); + clearStatusBit(.mstatus, 0x08); } pub inline fn sei() void { - asm volatile (""); + setStatusBit(.mstatus, 0x08); } pub const startup_logic = microzig.chip.startup_logic; diff --git a/src/esp32c3.zig b/src/package/registers.zig similarity index 100% rename from src/esp32c3.zig rename to src/package/registers.zig