File structure, draft 1

wch-ch32v003
Felix (xq) Queißner 3 years ago
parent e32d230c07
commit bbfdb421d8

1
.gitattributes vendored

@ -0,0 +1 @@
*.zig text=auto eol=lf

1
.gitignore vendored

@ -0,0 +1 @@
zig-cache/

@ -0,0 +1,178 @@
//! Some words on the build script here:
//! We cannot use a test runner here as we're building for freestanding.
//! This means we need to use addExecutable() instead of using
const std = @import("std");
const Board = struct {
name: []const u8,
path: []const u8,
chip: Chip,
};
const Chip = struct {
name: []const u8,
path: []const u8,
cpu: Cpu,
};
const Cpu = struct {
name: []const u8,
path: []const u8,
target: std.zig.CrossTarget,
linker_script: []const u8,
};
pub const Backing = union(enum) {
board: Board,
chip: Chip,
};
fn addEmbeddedExecutable(builder: *std.build.Builder, name: []const u8, source: []const u8, backing: Backing) *std.build.LibExeObjStep {
const Pkg = std.build.Pkg;
const exe = builder.addExecutable(name, source);
// TODO:
// - Generate the linker scripts from the "chip" or "board" package instead of using hardcoded ones.
// - This requires building another tool that runs on the host that compiles those files and emits the linker script.
// - src/tools/linkerscript-gen.zig is the source file for this
exe.bundle_compiler_rt = false;
switch (backing) {
.chip => |chip| {
exe.addBuildOption(bool, "microzig_has_board", false);
exe.addBuildOption([]const u8, "microzig_chip_name", chip.name);
exe.addBuildOption([]const u8, "microzig_cpu_name", chip.cpu.name);
exe.setTarget(chip.cpu.target);
exe.setLinkerScriptPath(chip.cpu.linker_script);
exe.addPackage(Pkg{
.name = "microzig",
.path = "src/core/microzig.zig",
.dependencies = &[_]Pkg{
Pkg{
.name = "chip",
.path = chip.path,
.dependencies = &[_]Pkg{
Pkg{
.name = "cpu",
.path = chip.cpu.path,
},
},
},
},
});
},
.board => |board| {
exe.addBuildOption(bool, "microzig_has_board", true);
exe.addBuildOption([]const u8, "microzig_board_name", board.name);
exe.addBuildOption([]const u8, "microzig_chip_name", board.chip.name);
exe.addBuildOption([]const u8, "microzig_cpu_name", board.chip.cpu.name);
exe.setTarget(board.chip.cpu.target);
exe.setLinkerScriptPath(board.chip.cpu.linker_script);
exe.addPackage(Pkg{
.name = "microzig",
.path = "src/core/microzig.zig",
.dependencies = &[_]Pkg{
Pkg{
.name = "board",
.path = board.path,
.dependencies = &[_]Pkg{
Pkg{
.name = "chip",
.path = board.chip.path,
.dependencies = &[_]Pkg{
Pkg{
.name = "cpu",
.path = board.chip.cpu.path,
},
},
},
},
},
},
});
},
}
return exe;
}
const pkgs = struct {
const cpus = struct {
const avr5 = Cpu{
.name = "avr",
.path = "src/modules/cpus/avr/avr5.zig",
.linker_script = "src/modules/cpus/avr/linker.ld",
.target = std.zig.CrossTarget{
.cpu_arch = .avr,
.cpu_model = .{ .explicit = &std.Target.avr.cpu.avr5 },
.os_tag = .freestanding,
.abi = .eabi,
},
};
const cortex_m3 = Cpu{
.name = "cortex-m3",
.path = "src/modules/cpus/cortex-m3/cortex-m3.zig",
.linker_script = "src/modules/cpus/cortex-m3/linker.ld",
.target = std.zig.CrossTarget{
.cpu_arch = .arm,
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m3 },
.os_tag = .freestanding,
.abi = .eabi,
},
};
};
const chips = struct {
const atmega328p = Chip{
.name = "AtMega328p",
.path = "src/modules/chips/atmega328p/atmega328p.zig",
.cpu = cpus.avr5,
};
const lpc1768 = Chip{
.name = "mcu",
.path = "src/modules/chips/lpc1768/lpc1768.zig",
.cpu = cpus.cortex_m3,
};
};
const boards = struct {
const arduino_nano = Board{
.name = "board",
.path = "src/modules/boards/arduino-nano/arduino-nano.zig",
.chip = chips.atmega328p,
};
const mbed_lpc1768 = Board{
.name = "mbed LPC1768",
.path = "src/modules/boards/mbed-lpc1768/mbed-lpc1768.zig",
.chip = chips.lpc1768,
};
};
};
pub fn build(b: *std.build.Builder) void {
const mode = b.standardReleaseOptions();
const test_step = b.step("test", "Builds and runs the library test suite");
const BuildConfig = struct { name: []const u8, backing: Backing };
const all_backings = [_]BuildConfig{
BuildConfig{ .name = "boards.arduino_nano", .backing = Backing{ .board = pkgs.boards.arduino_nano } },
BuildConfig{ .name = "boards.mbed_lpc1768", .backing = Backing{ .board = pkgs.boards.mbed_lpc1768 } },
BuildConfig{ .name = "chips.atmega328p", .backing = Backing{ .chip = pkgs.chips.atmega328p } },
BuildConfig{ .name = "chips.lpc1768", .backing = Backing{ .chip = pkgs.chips.lpc1768 } },
};
inline for (all_backings) |cfg| {
const exe = addEmbeddedExecutable(
b,
"test-minimal-" ++ cfg.name,
"tests/minimal.zig",
cfg.backing,
);
exe.setBuildMode(mode);
test_step.dependOn(&exe.step);
}
}

@ -0,0 +1,2 @@
const std = @import("std");
const micro = @import("microzig.zig");

@ -0,0 +1,58 @@
const std = @import("std");
const micro = @import("microzig.zig");
/// Unmasks the given interrupt and enables its execution.
/// Note that interrupts must be globally enabled with `sei()` as well.
pub fn enable(comptime interrupt: anytype) void {
@panic("not implemented yet!");
}
/// Masks the given interrupt and disables its execution.
pub fn disable(comptime interrupt: anytype) void {
@panic("not implemented yet!");
}
/// Returns true when the given interrupt is unmasked.
pub fn isEnabled(comptime interrupt: anytype) bool {
@panic("not implemented yet!");
}
/// *Set Enable Interrupt*, will enable IRQs globally, but keep the masking done via
/// `enable` and `disable` intact.
pub fn sei() void {
@panic("not implemented yet!");
}
/// *Clear Enable Interrupt*, will disable IRQs globally, but keep the masking done via
/// `enable` and `disable` intact.
pub fn cli() void {
@panic("not implemented yet!");
}
/// Returns true, when interrupts are globally enabled via `sei()`.
pub fn areGloballyEnabled() bool {
@panic("not implemented yet!");
}
/// Enters a critical section and disables interrupts globally.
/// Call `.leave()` on the return value to restore the previous state.
pub fn enterCriticalSection() CriticalSection {
var section = CriticalSection{
.enable_on_leave = areGloballyEnabled(),
};
cli();
return section;
}
/// A critical section structure that allows restoring the interrupt
/// status that was set before entering.
const CriticalSection = struct {
enable_on_leave: bool,
/// Leaves the critical section and restores the interrupt state.
pub fn leave(self: @This()) void {
if (self.enable_on_leave) {
sei();
}
}
};

@ -0,0 +1,19 @@
const std = @import("std");
/// Module that helps with interrupt handling.
pub const interrupts = @import("interrupts.zig");
/// The microzig panic handler. Will disable interrupts and loop endlessly.
/// Export this symbol from your main file to enable microzig:
/// ```
/// const micro = @import("microzig");
/// pub const panic = micro.panic;
/// ```
pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
while (true) {
interrupts.cli();
// "this loop has side effects, don't optimize the endless loop away please. thanks!"
asm volatile ("" ::: "memory");
}
}

@ -0,0 +1,2 @@
const std = @import("std");
const micro = @import("microzig.zig");

@ -0,0 +1,31 @@
MEMORY
{
flash (rx) : ORIGIN = 0, LENGTH = 32K
ram (rw!x) : ORIGIN = 0x800100, LENGTH = 2K
}
SECTIONS
{
.text :
{
KEEP(*(.vectors))
*(.text*)
} > flash
.data :
{
__data_start = .;
*(.rodata*)
*(.data*)
__data_end = .;
} > ram AT> flash
.bss (NOLOAD) :
{
__bss_start = .;
*(.bss*)
__bss_end = .;
} > ram
__data_load_start = LOADADDR(.data);
}

@ -0,0 +1,79 @@
MEMORY
{
flash (rx!w) : ORIGIN = 0x00000000, LENGTH = 512k
ram0 (rw!x) : ORIGIN = 0x10000000, LENGTH = 32k
ram1 (rw!x) : ORIGIN = 0x2007C000, LENGTH = 32k
}
SECTIONS
{
. = 0;
/* Code-Speicher im Flash ***********/
.text :
{
__code_start__ = .;
LONG( ORIGIN(ram1) + LENGTH(ram1) )
KEEP(*( .isr_vector ));
*(.text)
*(.text.*)
. = ALIGN(4);
__code_end__ = .;
*(.gnu.linkonce.t.*)
*(.glue_7)
*(.glue_7t)
*(.gcc_except_table)
*(.gnu.linkonce.r.*)
} >flash
. = ALIGN(4);
/* contains unwinding information */
.ARM.exidx : {
. = ALIGN(4);
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
. = ALIGN(4);
} >flash
. = ALIGN(4);
/* Konstanten im Flash ****************/
.rodata . :
{
. = ALIGN(4);
*(.rodata)
. = ALIGN(4);
*(.rodata.*)
} >flash
. = ALIGN(4);
PROVIDE (__text__end = .);
.data : AT (__text__end)
{
PROVIDE (__data__start = .);
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
PROVIDE (__data__end = .);
} >ram0
.bss :
{
PROVIDE (__bss__start = .);
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b*)
. = ALIGN(4);
PROVIDE (__bss__end = .);
} >ram0
_end = .;
PROVIDE (end = .);
}

@ -0,0 +1,20 @@
const std = @import("std");
const chip = @import("chip");
pub fn main() !u8 {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
const allocator = &arena.deinit();
const args = try std.process.argsAlloc(allocator);
if (args.len < 2) {
std.log.err("Missing CLI argument. Give the output file name!");
return 1;
}
var dest_file = try std.fs.cwd().createFile(args[1], .{});
defer dest_file.close();
try dest_file.writeAll("THIS FILE IS NOT USABLE YET!");
}

@ -0,0 +1,8 @@
const micro = @import("microzig");
// this will instantiate microzig and pull in all dependencies
pub const panic = micro.panic;
pub fn main() void {
return;
}
Loading…
Cancel
Save