Blinky! \o/

wch-ch32v003
Felix "xq" Queißner 2 years ago
parent 33984fa960
commit e84264e64b

@ -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();

@ -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

@ -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

@ -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;
}
}
};

@ -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,
};
};

@ -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;

Loading…
Cancel
Save