-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
53cffe1
commit 46c579a
Showing
12 changed files
with
692 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
zig-cache/ | ||
riscv-zig-blink.bin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# riscv-zig-blink | ||
|
||
Written against zig 0.5.0-518dbd30c | ||
|
||
Run `zig build --help` from this directory for usage and options. | ||
`zig build run -Drelease` will compile and run on your connected FOMU. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
const std = @import("std"); | ||
const Builder = std.build.Builder; | ||
|
||
pub fn build(b: *Builder) void { | ||
b.setPreferredReleaseMode(.ReleaseSmall); | ||
const mode = b.standardReleaseOptions(); | ||
|
||
const elf = b.addExecutable("riscv-zig-blink", "src/main.zig"); | ||
elf.setTheTarget(.{ | ||
.Cross = .{ | ||
.arch = .riscv32, | ||
.os = .freestanding, | ||
.abi = .none, | ||
.cpu_features = .{ | ||
.cpu = &std.Target.riscv.cpu.generic_rv32, | ||
.features = std.Target.Cpu.Feature.Set.empty, | ||
}, | ||
}, | ||
}); | ||
elf.setLinkerScriptPath("ld/linker.ld"); | ||
elf.setBuildMode(mode); | ||
elf.setOutputDir("."); | ||
|
||
const binary = b.addSystemCommand(&[_][]const u8{ | ||
b.option([]const u8, "objcopy", "objcopy executable to use (defaults to llvm-objcopy)") orelse "llvm-objcopy", | ||
"-I", | ||
"elf32-littleriscv", | ||
"-O", | ||
"binary", | ||
}); | ||
binary.addArtifactArg(elf); | ||
binary.addArg("riscv-zig-blink.bin"); | ||
b.default_step.dependOn(&binary.step); | ||
|
||
const run_cmd = b.addSystemCommand(&[_][]const u8{ | ||
"dfu-util", | ||
"-D", | ||
"riscv-zig-blink.bin", | ||
}); | ||
run_cmd.step.dependOn(&binary.step); | ||
const run_step = b.step("run", "Upload and run the app on your FOMU"); | ||
run_step.dependOn(&run_cmd.step); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
ENTRY(_start) | ||
|
||
__DYNAMIC = 0; | ||
|
||
MEMORY { | ||
sram : ORIGIN = 0x10000000, LENGTH = 0x00020000 | ||
rom : ORIGIN = 0x20040000, LENGTH = 0x100000 /* 1 MBit */ | ||
} | ||
|
||
SECTIONS | ||
{ | ||
.text : | ||
{ | ||
_ftext = .; | ||
*(.text.start) | ||
*(.text .stub .text.* .gnu.linkonce.t.*) | ||
_etext = .; | ||
} > rom | ||
|
||
.rodata : | ||
{ | ||
. = ALIGN(4); | ||
_frodata = .; | ||
*(.rodata .rodata.* .gnu.linkonce.r.*) | ||
*(.rodata1) | ||
*(.srodata) | ||
. = ALIGN(4); | ||
_erodata = .; | ||
} > rom | ||
|
||
.data : AT (ADDR(.rodata) + SIZEOF (.rodata)) | ||
{ | ||
. = ALIGN(4); | ||
_fdata = .; | ||
*(.data .data.* .gnu.linkonce.d.*) | ||
*(.data1) | ||
*(.ramtext .ramtext.*) | ||
_gp = ALIGN(16); | ||
*(.sdata .sdata.* .gnu.linkonce.s.* .sdata2 .sdata2.*) | ||
_edata = ALIGN(16); /* Make sure _edata is >= _gp. */ | ||
} > sram | ||
|
||
.bss : | ||
{ | ||
. = ALIGN(4); | ||
_fbss = .; | ||
*(.dynsbss) | ||
*(.sbss .sbss.* .gnu.linkonce.sb.*) | ||
*(.scommon) | ||
*(.dynbss) | ||
*(.bss .bss.* .gnu.linkonce.b.*) | ||
*(COMMON) | ||
. = ALIGN(4); | ||
_ebss = .; | ||
} > sram | ||
|
||
_end = .; | ||
} | ||
|
||
PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 4); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
const builtin = @import("builtin"); | ||
const std = @import("std"); | ||
|
||
pub const MESSIBLE = @import("./fomu/messible.zig").MESSIBLE; | ||
pub const REBOOT = @import("./fomu/reboot.zig").REBOOT; | ||
pub const RGB = @import("./fomu/rgb.zig").RGB; | ||
pub const TIMER0 = @import("./fomu/timer0.zig").TIMER0; | ||
pub const TOUCH = @import("./fomu/touch.zig").TOUCH; | ||
|
||
pub const SYSTEM_CLOCK_FREQUENCY = 12000000; | ||
|
||
pub const start = @import("./fomu/start.zig"); | ||
// This forces start.zig file to be imported | ||
comptime { | ||
_ = start; | ||
} | ||
|
||
/// Panic function that sets LED to red and flashing + prints the panic message over messible | ||
pub fn panic(message: []const u8, stack_trace: ?*builtin.StackTrace) noreturn { | ||
@setCold(true); | ||
|
||
// Put LED into non-raw flashing mode | ||
RGB.CTRL.* = .{ | ||
.EXE = true, | ||
.CURREN = true, | ||
.RGBLEDEN = true, | ||
.RRAW = false, | ||
.GRAW = false, | ||
.BRAW = false, | ||
}; | ||
// Set colour to red | ||
RGB.setColour(255, 0, 0); | ||
// Enable the LED driver, and set 250 Hz mode. | ||
RGB.setControlRegister(.{ | ||
.enable = true, | ||
.fr = .@"250", | ||
.quick_stop = false, | ||
.outskew = false, | ||
.output_polarity = .active_high, | ||
.pwm_mode = .linear, | ||
.BRMSBEXT = 0, | ||
}); | ||
|
||
messibleOutstream.print("PANIC: {}\r\n", .{message}) catch void; | ||
|
||
while (true) { | ||
// TODO: Use @breakpoint() once https://reviews.llvm.org/D69390 is available | ||
asm volatile ("ebreak"); | ||
} | ||
} | ||
|
||
const OutStream = std.io.OutStream(error{}); | ||
pub const messibleOutstream = &OutStream{ | ||
.writeFn = struct { | ||
pub fn messibleWrite(self: *const OutStream, bytes: []const u8) error{}!void { | ||
var left: []const u8 = bytes; | ||
while (left.len > 0) { | ||
const bytes_written = MESSIBLE.write(left); | ||
left = left[bytes_written..]; | ||
} | ||
} | ||
}.messibleWrite, | ||
}; | ||
|
||
const InStream = std.io.InStream(error{}); | ||
pub const messibleInstream = &InStream{ | ||
.writeFn = struct { | ||
pub fn messibleRead(self: *const InStream, buffer: []u8) error{}!usize { | ||
while (true) { | ||
const bytes_read = MESSIBLE.read(buffer); | ||
if (bytes_read != 0) return bytes_read; | ||
} | ||
} | ||
}.messibleRead, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/// Messible: An Ansible for Messages | ||
/// https://rm.fomu.im/messible.html | ||
/// | ||
/// An Ansible is a system for instant communication across vast distances, | ||
/// from a small portable device to a huge terminal far away. A Messible is | ||
/// a message- passing system from embedded devices to a host system. You can | ||
/// use it to get very simple printf()-style support over a debug channel. | ||
/// | ||
/// The Messible assumes the host has a way to peek into the device’s memory | ||
/// space. This is the case with the Wishbone bridge, which allows both the | ||
/// device and the host to access the same memory. | ||
/// | ||
/// At its core, a Messible is a FIFO. As long as the STATUS.FULL bit is 0, | ||
/// the device can write data into the Messible by writing into the IN. | ||
/// However, if this value is 1, you need to decide if you want to wait for it | ||
/// to empty (if the other side is just slow), or if you want to drop the | ||
/// message. From the host side, you need to read STATUS.HAVE to see if there | ||
/// is data in the FIFO. If there is, read OUT to get the most recent byte, | ||
/// which automatically advances the READ pointer. | ||
pub const MESSIBLE = struct { | ||
const base = 0xe0008000; | ||
|
||
/// Write half of the FIFO to send data out the Messible. Writing to this register advances the write pointer automatically. | ||
pub const IN = @intToPtr(*volatile u8, base + 0x0); | ||
|
||
/// Read half of the FIFO to receive data on the Messible. Reading from this register advances the read pointer automatically. | ||
pub const OUT = @intToPtr(*volatile u8, base + 0x4); | ||
|
||
pub const STATUS = @intToPtr(*volatile packed struct { | ||
/// if more data can fit into the IN FIFO. | ||
FULL: bool, | ||
|
||
/// if data can be read from the OUT FIFO. | ||
HAVE: bool, | ||
}, base + 0x8); | ||
|
||
pub fn write(data: []const u8) usize { | ||
for (data) |c, i| { | ||
if (STATUS.*.FULL) return i; | ||
IN.* = c; | ||
} | ||
return data.len; | ||
} | ||
|
||
pub fn read(dst: []u8) usize { | ||
for (dst) |*c, i| { | ||
if (!STATUS.*.HAVE) return i; | ||
c.* = OUT.*; | ||
} | ||
return dst.len; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/// https://rm.fomu.im/reboot.html | ||
pub const REBOOT = struct { | ||
const base = 0xe0006000; | ||
|
||
/// Provides support for rebooting the FPGA. | ||
/// You can select which of the four images to reboot to. | ||
pub const CTRL = @intToPtr(*volatile packed struct { | ||
/// Which image to reboot to. SB_WARMBOOT supports four images that are configured at FPGA startup. | ||
/// The bootloader is image 0, so set these bits to 0 to reboot back into the bootloader. | ||
image: u2, | ||
|
||
/// A reboot key used to prevent accidental reboots when writing to random areas of memory. | ||
/// To initiate a reboot, set this to 0b101011. | ||
key: u6, | ||
}, base + 0x0); | ||
|
||
/// This sets the reset vector for the VexRiscv. | ||
/// This address will be used whenever the CPU is reset, for example | ||
/// through a debug bridge. You should update this address whenever | ||
/// you load a new program, to enable the debugger to run `mon reset` | ||
pub const ADDR = @intToPtr(*volatile u32, base + 0x4); | ||
}; |
Oops, something went wrong.