-
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 d3e5050
Showing
12 changed files
with
442 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,42 @@ | ||
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); | ||
|
||
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,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,38 @@ | ||
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 start = @import("./fomu/start.zig"); | ||
// This forces start.zig file to be imported | ||
comptime { | ||
_ = start; | ||
} | ||
|
||
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); | ||
}; |
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,56 @@ | ||
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; | ||
|
||
export 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 | ||
); | ||
|
||
// zero out bss | ||
asm volatile ( | ||
\\ la a0, _fbss | ||
\\ la a1, _ebss | ||
\\bss_loop: | ||
\\ beq a0, a1, bss_done | ||
\\ sw zero, 0(a0) | ||
\\ add a0, a0,4 | ||
\\ j bss_loop | ||
\\bss_done: | ||
); | ||
|
||
// copy data from data rom (which is after rodata) to data | ||
asm volatile ( | ||
\\ la t0, _erodata | ||
\\ la t1, _fdata | ||
\\ la t2, _edata | ||
\\data_loop: | ||
\\ lw t3, 0(t0) | ||
\\ sw t3, 0(t1) | ||
\\ addi t0, t0, 4 | ||
\\ addi t1, t1, 4 | ||
\\ bltu t1, t2, data_loop | ||
); | ||
|
||
// call user's main | ||
root.main(); | ||
} |
Oops, something went wrong.