Skip to content

Commit 6e4faa6

Browse files
author
Felix "xq" Queißner
committed
xq's changes in Ashet
1 parent 79d5400 commit 6e4faa6

File tree

7 files changed

+1668
-13
lines changed

7 files changed

+1668
-13
lines changed

core/src/cpus/cortex_m.zig

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

579579
const vector_count = @sizeOf(microzig.chip.VectorTable) / @sizeOf(usize);
580+
const mregs = @import("m-profile.zig");
580581

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

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

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

671686
for (@typeInfo(@TypeOf(microzig.options.interrupts)).@"struct".fields) |field| {
@@ -677,6 +692,109 @@ pub const startup_logic = struct {
677692

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

682800
fn is_ramimage() bool {

0 commit comments

Comments
 (0)