-
Notifications
You must be signed in to change notification settings - Fork 63
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 1ee0ab1
Showing
10 changed files
with
322 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,39 @@ | ||
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 = .gnu, | ||
.cpu_features = .{ .features = std.Target.Cpu.Feature.Set.empty }, | ||
}, | ||
}); | ||
elf.setLinkerScriptPath("ld/linker.ld"); | ||
elf.setBuildMode(mode); | ||
|
||
const binary = b.addSystemCommand(&[_][]const u8{ | ||
"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,59 @@ | ||
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 = .; | ||
_end = .; | ||
} > sram | ||
} | ||
|
||
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,6 @@ | ||
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 TOUCH = @import("./fomu/touch.zig").TOUCH; | ||
|
||
pub const start = @import("./fomu/start.zig"); |
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; | ||
OUT.* = c; | ||
} | ||
return data.len; | ||
} | ||
|
||
pub fn read(dst: []u8) usize { | ||
for (dst) |*c, i| { | ||
if (!STATUS.*.HAVE) return i; | ||
c.* = IN.*; | ||
} | ||
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); | ||
}; |
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,55 @@ | ||
/// https://rm.fomu.im/rgb.html | ||
pub const RGB = struct { | ||
const base = 0xe0006800; | ||
|
||
/// This is the value for the SB_LEDDA_IP.DAT register. | ||
/// It is directly written into the SB_LEDDA_IP hardware block, so you | ||
/// should refer to http://www.latticesemi.com/view_document?document_id=50668. | ||
/// The contents of this register are written to the address specified | ||
/// in ADDR immediately upon writing this register. | ||
pub const DAT = @intToPtr(*volatile u8, base + 0x0); | ||
|
||
/// This register is directly connected to SB_LEDDA_IP.ADDR. | ||
/// This register controls the address that is updated whenever DAT is written. | ||
/// Writing to this register has no immediate effect – data isn’t written until the DAT register is written. | ||
pub const ADDR = @intToPtr(*volatile u4, base + 0x4); | ||
|
||
/// Control logic for the RGB LED and LEDDA hardware PWM LED block. | ||
pub const CTRL = @intToPtr(*volatile packed struct { | ||
/// Enable the fading pattern? | ||
/// Connected to `SB_LEDDA_IP.LEDDEXE`. | ||
EXE: bool, | ||
|
||
/// Enable the current source? | ||
/// Connected to `SB_RGBA_DRV.CURREN`. | ||
CURREN: bool, | ||
|
||
/// Enable the RGB PWM control logic? | ||
/// Connected to `SB_RGBA_DRV.RGBLEDEN`. | ||
RGBLEDEN: bool, | ||
|
||
/// Enable raw control of the red LED via the RAW.R register. | ||
RRAW: bool, | ||
|
||
/// Enable raw control of the green LED via the RAW.G register. | ||
GRAW: bool, | ||
|
||
/// Enable raw control of the blue LED via the RAW.B register. | ||
BRAW: bool, | ||
}, base + 0x8); | ||
|
||
/// Normally the hardware SB_LEDDA_IP block controls the brightness of the | ||
/// LED, creating a gentle fading pattern. | ||
/// However, by setting the appropriate bit in CTRL, it is possible to | ||
/// manually control the three individual LEDs. | ||
pub const RAW = @intToPtr(*volatile packed struct { | ||
/// Red | ||
R: bool, | ||
|
||
/// Green | ||
G: bool, | ||
|
||
/// Blue | ||
B: bool, | ||
}, base + 0xc); | ||
}; |
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,42 @@ | ||
const root = @import("root"); | ||
const std = @import("std"); | ||
|
||
extern var _ftext: u8; | ||
extern var _etext: u8; | ||
extern var _frodata: u8 align(4); | ||
extern var _erodata: u8 align(4); | ||
extern var _fdata: u8 align(4); | ||
extern var _gp: u8 align(16); | ||
extern var _edata: u8 align(16); | ||
extern var _fbss: u8 align(4); | ||
extern var _ebss: u8 align(4); | ||
extern var _end: u8; | ||
extern var _fstack: u8; | ||
|
||
pub fn _start() linksection(".text.start") callconv(.Naked) noreturn { | ||
asm volatile ( | ||
\\ j over_magic | ||
\\ .word 0xb469075a // Magic value for config flags | ||
\\ .word 0x00000020 // USB_NO_RESET flag so we can attach the debugger | ||
\\ over_magic: | ||
); | ||
|
||
// set the stack pointer to `&_fstack` | ||
asm volatile ( | ||
\\la sp, _fstack + 4 | ||
); | ||
|
||
const text = @ptrCast([*]u8, &_ftext)[0..(@ptrToInt(&_etext) - @ptrToInt(&_ftext))]; | ||
const rodata = @ptrCast([*]align(4) const u8, &_erodata)[0..(@ptrToInt(&_erodata) - @ptrToInt(&_frodata))]; | ||
const bss = @ptrCast([*]align(4) u8, &_fbss)[0..(@ptrToInt(&_ebss) - @ptrToInt(&_fbss))]; | ||
const data = @ptrCast([*]align(4) u8, &_fdata)[0..(@ptrToInt(&_edata) - @ptrToInt(&_fdata))]; | ||
|
||
// zero out bss | ||
std.mem.set(u8, bss, 0); | ||
|
||
// copy data from rodata to data | ||
std.mem.copy(u8, data, rodata); | ||
|
||
// call user's main | ||
root.main(); | ||
} |
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,13 @@ | ||
/// https://rm.fomu.im/touch.html | ||
pub const TOUCH = struct { | ||
const base = 0xe0005800; | ||
|
||
/// Output values for pads 1-4 | ||
pub const TOUCH_O = @intToPtr(*volatile u4, base + 0x0); | ||
|
||
/// Output enable control for pads 1-4 | ||
pub const TOUCH_OE = @intToPtr(*volatile u4, base + 0x4); | ||
|
||
/// Input value for pads 1-4 | ||
pub const TOUCH_1 = @intToPtr(*volatile u4, base + 0x8); | ||
}; |
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,32 @@ | ||
const builtin = @import("builtin"); | ||
const std = @import("std"); | ||
const fomu = @import("./fomu.zig"); | ||
|
||
// export our _start symbol | ||
comptime { | ||
@export(fomu.start._start, .{ .name = "_start" }); | ||
} | ||
|
||
pub fn panic(message: []const u8, stack_trace: ?*builtin.StackTrace) noreturn { | ||
@setCold(true); | ||
while (true) {} | ||
} | ||
|
||
pub fn main() noreturn { | ||
// Turn on the green LED | ||
fomu.RGB.CTRL.* = .{ | ||
.EXE = false, | ||
.CURREN = true, | ||
.RGBLEDEN = true, | ||
.RRAW = true, | ||
.GRAW = true, | ||
.BRAW = true, | ||
}; | ||
fomu.RGB.RAW.* = .{ | ||
.R = false, | ||
.G = true, | ||
.B = false, | ||
}; | ||
while (true) {} | ||
} | ||
|