Skip to content

Commit dd199a3

Browse files
author
Felix "xq" Queißner
committed
xq's changes in Ashet
1 parent dd8544d commit dd199a3

File tree

7 files changed

+1670
-14
lines changed

7 files changed

+1670
-14
lines changed

core/src/cpus/cortex_m.zig

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ pub fn clrex() void {
576576
}
577577

578578
const vector_count = @sizeOf(microzig.chip.VectorTable) / @sizeOf(usize);
579+
const mregs = @import("m-profile.zig");
579580

580581
var ram_vectors: [vector_count]usize align(256) = undefined;
581582

@@ -630,6 +631,15 @@ pub const startup_logic = struct {
630631
@memcpy(data_start[0..data_len], data_src[0..data_len]);
631632
}
632633

634+
// We want the hardfault to be split into smaller parts:
635+
mregs.registers.system_control_block.shcrs.modify(.{
636+
.memfault_enabled = true,
637+
.busfault_enabled = true,
638+
.usagefault_enabled = true,
639+
});
640+
641+
enable_fault_irq();
642+
633643
// Move vector table to RAM if requested
634644
if (interrupt.has_ram_vectors()) {
635645
// Copy vector table to RAM and set VTOR to point to it
@@ -638,7 +648,6 @@ pub const startup_logic = struct {
638648
@export(&ram_vectors, .{
639649
.name = "_ram_vectors",
640650
.section = "ram_vectors",
641-
.linkage = .strong,
642651
});
643652
} else {
644653
@export(&ram_vectors, .{
@@ -665,6 +674,12 @@ pub const startup_logic = struct {
665674
var tmp: VectorTable = .{
666675
.initial_stack_pointer = microzig.config.end_of_stack,
667676
.Reset = .{ .c = microzig.cpu.startup_logic._start },
677+
678+
.NMI = panic_handler("NMI"),
679+
.HardFault = panic_handler("HardFault"),
680+
.MemManageFault = panic_handler("MemManageFault"),
681+
.BusFault = make_fault_handler(default_bus_fault_handler), // Exception 5
682+
.UsageFault = make_fault_handler(default_usage_fault_handler), // Exception 6
668683
};
669684

670685
for (@typeInfo(@TypeOf(microzig_options.interrupts)).@"struct".fields) |field| {
@@ -676,6 +691,109 @@ pub const startup_logic = struct {
676691

677692
break :blk tmp;
678693
};
694+
695+
fn panic_handler(comptime msg: []const u8) microzig.interrupt.Handler {
696+
const T = struct {
697+
fn do_panic() callconv(.C) noreturn {
698+
@panic(msg);
699+
}
700+
};
701+
702+
return .{ .c = T.do_panic };
703+
}
704+
705+
const ContextStateFrame = extern struct {
706+
r0: u32,
707+
r1: u32,
708+
r2: u32,
709+
r3: u32,
710+
r12: u32,
711+
lr: u32,
712+
return_address: u32,
713+
xpsr: u32,
714+
};
715+
716+
fn make_fault_handler(comptime handler: *const fn (context: *ContextStateFrame) callconv(.C) void) microzig.interrupt.Handler {
717+
const T = struct {
718+
fn invoke() callconv(.C) void {
719+
// See this article on how we use that:
720+
// https://interrupt.memfault.com/blog/cortex-m-hardfault-debug
721+
asm volatile (
722+
\\
723+
// Check 2th bit of LR.
724+
\\tst lr, #4
725+
// Do "if then else" equal
726+
\\ite eq
727+
// if equals, we use the MSP
728+
\\mrseq r0, msp
729+
// otherwise, we use the PSP
730+
\\mrsne r0, psp
731+
// Then we branch to our handler:
732+
\\b %[handler]
733+
:
734+
: [handler] "s" (handler),
735+
);
736+
}
737+
};
738+
739+
return .{ .c = T.invoke };
740+
}
741+
742+
const logger = std.log.scoped(.cortex_m);
743+
744+
fn default_bus_fault_handler(context: *ContextStateFrame) callconv(.C) void {
745+
const bfsr = mregs.registers.system_control_block.bfsr.read();
746+
747+
logger.err("Bus Fault:", .{});
748+
logger.err(" context = r0:0x{X:0>8} r1:0x{X:0>8} r2:0x{X:0>8} r3:0x{X:0>8}", .{
749+
context.r0,
750+
context.r1,
751+
context.r2,
752+
context.r3,
753+
});
754+
logger.err(" r12:0x{X:0>8} lr:0x{X:0>8} ra:0x{X:0>8} xpsr:0x{X:0>8}", .{
755+
context.r12,
756+
context.lr,
757+
context.return_address,
758+
context.xpsr,
759+
});
760+
logger.err(" instruction bus error = {}", .{bfsr.instruction_bus_error});
761+
logger.err(" precice data bus error = {}", .{bfsr.precice_data_bus_error});
762+
logger.err(" imprecice data bus error = {}", .{bfsr.imprecice_data_bus_error});
763+
logger.err(" unstacking exception error = {}", .{bfsr.unstacking_exception_error});
764+
logger.err(" exception stacking error = {}", .{bfsr.exception_stacking_error});
765+
logger.err(" busfault address register valid = {}", .{bfsr.busfault_address_register_valid});
766+
if (bfsr.busfault_address_register_valid) {
767+
const address = mregs.registers.system_control_block.bfar.read().ADDRESS;
768+
logger.err(" busfault address register = 0x{X:0>8}", .{address});
769+
}
770+
}
771+
772+
fn default_usage_fault_handler(context: *ContextStateFrame) callconv(.C) void {
773+
const ufsr = mregs.registers.system_control_block.ufsr.read();
774+
775+
logger.err("Usage Fault:", .{});
776+
logger.err(" context = r0:0x{X:0>8} r1:0x{X:0>8} r2:0x{X:0>8} r3:0x{X:0>8}", .{
777+
context.r0,
778+
context.r1,
779+
context.r2,
780+
context.r3,
781+
});
782+
logger.err(" r12:0x{X:0>8} lr:0x{X:0>8} ra:0x{X:0>8} xpsr:0x{X:0>8}", .{
783+
context.r12,
784+
context.lr,
785+
context.return_address,
786+
context.xpsr,
787+
});
788+
logger.err(" undefined instruction = {}", .{ufsr.undefined_instruction});
789+
logger.err(" invalid state = {}", .{ufsr.invalid_state});
790+
logger.err(" invalid pc load = {}", .{ufsr.invalid_pc_load});
791+
logger.err(" missing coprocessor usage = {}", .{ufsr.missing_coprocessor_usage});
792+
logger.err(" unaligned memory access = {}", .{ufsr.unaligned_memory_access});
793+
logger.err(" divide by zero = {}", .{ufsr.divide_by_zero});
794+
795+
@panic("usage fault");
796+
}
679797
};
680798

681799
fn is_ramimage() bool {

0 commit comments

Comments
 (0)