Avr interrupt overloading (#29)

* mostly implemented, need different patch in order to wire it in

* add generated code

* turned interrupts back on

* fix symbol names for avr

* export in cpu file

* Emits a function instead of a `void` symbol.

* add interrupt test to avr

* Removes invalid comment.

Co-authored-by: Felix "xq" Queißner <git@masterq32.de>
wch-ch32v003
Matt Knight 3 years ago committed by GitHub
parent 823ff6577f
commit b2793e2589
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -31,7 +31,7 @@ pub fn build(b: *std.build.Builder) !void {
Test{ .name = "uart-sync", .source = "tests/uart-sync.zig", .uses_uart = true, .on_avr = false }, Test{ .name = "uart-sync", .source = "tests/uart-sync.zig", .uses_uart = true, .on_avr = false },
// Note: this example uses the systick interrupt and therefore only for arm microcontrollers // Note: this example uses the systick interrupt and therefore only for arm microcontrollers
Test{ .name = "interrupt", .source = "tests/interrupt.zig", .on_avr = false }, Test{ .name = "interrupt", .source = "tests/interrupt.zig", .on_avr = true },
}; };
const filter = b.option(std.Target.Cpu.Arch, "filter-target", "Filters for a certain cpu target"); const filter = b.option(std.Target.Cpu.Arch, "filter-target", "Filters for a certain cpu target");

@ -1,5 +1,6 @@
const std = @import("std"); const std = @import("std");
const micro = @import("microzig"); const micro = @import("microzig");
pub usingnamespace @import("registers.zig");
pub const cpu = micro.cpu; pub const cpu = micro.cpu;
const Port = enum(u8) { const Port = enum(u8) {

File diff suppressed because it is too large Load Diff

@ -1,4 +1,5 @@
const std = @import("std"); const std = @import("std");
const microzig = @import("microzig");
pub inline fn sei() void { pub inline fn sei() void {
asm volatile ("sei"); asm volatile ("sei");
@ -24,46 +25,77 @@ pub inline fn cbi(comptime reg: u5, comptime bit: u3) void {
); );
} }
pub const startup_logic = struct { pub const vector_table = blk: {
comptime { std.debug.assert(std.mem.eql(u8, "RESET", std.meta.fields(microzig.chip.VectorTable)[0].name));
asm ( var asm_str: []const u8 = "jmp microzig_start\n";
\\.section microzig_flash_start
\\ jmp _start const has_interrupts = @hasDecl(microzig.app, "interrupts");
\\ jmp _unhandled_vector if (has_interrupts) {
\\ jmp _unhandled_vector if (@hasDecl(microzig.app.interrupts, "RESET"))
\\ jmp _unhandled_vector @compileError("Not allowed to overload the reset vector");
\\ jmp _unhandled_vector
\\ jmp _unhandled_vector inline for (std.meta.declarations(microzig.app.interrupts)) |decl| {
\\ jmp _unhandled_vector if (!@hasField(microzig.chip.VectorTable, decl.name)) {
\\ jmp _unhandled_vector var msg: []const u8 = "There is no such interrupt as '" ++ decl.name ++ "'. ISRs the 'interrupts' namespace must be one of:\n";
\\ jmp _unhandled_vector inline for (std.meta.fields(microzig.chip.VectorTable)) |field| {
\\ jmp _unhandled_vector if (!std.mem.eql(u8, "RESET", field.name)) {
\\ jmp _unhandled_vector msg = msg ++ " " ++ field.name ++ "\n";
\\ jmp _unhandled_vector }
\\ jmp _unhandled_vector }
\\ jmp _unhandled_vector
\\ jmp _unhandled_vector @compileError(msg);
\\ jmp _unhandled_vector }
\\ jmp _unhandled_vector }
\\ jmp _unhandled_vector }
\\ jmp _unhandled_vector
\\ jmp _unhandled_vector inline for (std.meta.fields(microzig.chip.VectorTable)[1..]) |field| {
\\ jmp _unhandled_vector const new_insn = if (has_interrupts) overload: {
\\ jmp _unhandled_vector if (@hasDecl(microzig.app.interrupts, field.name)) {
\\ jmp _unhandled_vector const handler = @field(microzig.app.interrupts, field.name);
\\ jmp _unhandled_vector const calling_convention = switch (@typeInfo(@TypeOf(@field(microzig.app.interrupts, field.name)))) {
\\ jmp _unhandled_vector .Fn => |info| info.calling_convention,
\\ jmp _unhandled_vector else => @compileError("Declarations in 'interrupts' namespace must all be functions. '" ++ field.name ++ "' is not a function"),
); };
const exported_fn = switch (calling_convention) {
.Unspecified => struct {
fn wrapper() callconv(.C) void {
if (calling_convention == .Unspecified) // TODO: workaround for some weird stage1 bug
@call(.{ .modifier = .always_inline }, handler, .{});
}
}.wrapper,
else => @compileError("Just leave interrupt handlers with an unspecified calling convention"),
};
const exported_name = "microzig_isr_" ++ field.name;
const options = .{ .name = exported_name, .linkage = .Strong };
@export(exported_fn, options);
break :overload "jmp " ++ exported_name;
} else {
break :overload "jmp microzig_unhandled_vector";
}
} else "jmp microzig_unhandled_vector";
asm_str = asm_str ++ new_insn ++ "\n";
} }
export fn _unhandled_vector() callconv(.Naked) noreturn { const T = struct {
fn _start() callconv(.Naked) void {
asm volatile (asm_str);
}
};
break :blk T._start;
};
pub const startup_logic = struct {
export fn microzig_unhandled_vector() callconv(.Naked) noreturn {
@panic("Unhandled interrupt"); @panic("Unhandled interrupt");
} }
extern fn microzig_main() noreturn; extern fn microzig_main() noreturn;
export fn _start() callconv(.Naked) noreturn { export fn microzig_start() callconv(.Naked) noreturn {
// At startup the stack pointer is at the end of RAM // At startup the stack pointer is at the end of RAM
// so, no need to set it manually! // so, no need to set it manually!

@ -1,4 +1,5 @@
const micro = @import("microzig"); const micro = @import("microzig");
const builtin = @import("builtin");
// this program will only work on arm microcontrollers, and it might not // this program will only work on arm microcontrollers, and it might not
// actually run correctly at first, it's just a test for declaring interrupts // actually run correctly at first, it's just a test for declaring interrupts
@ -6,14 +7,19 @@ const micro = @import("microzig");
pub const panic = micro.panic; pub const panic = micro.panic;
pub const interrupts = struct { pub const interrupts = switch (builtin.cpu.arch) {
pub fn SysTick() void { .avr => struct {
@panic("hit systick!"); pub fn INT0() void {
} @panic("hit PCINT0");
}
},
else => struct {
pub fn SysTick() void {
@panic("hit systick!");
}
},
}; };
pub fn main() void { pub fn main() void {
while (true) { while (true) {}
micro.cpu.wfi();
}
} }

Loading…
Cancel
Save