psoc-drivers 0.1.0

Hardware driver implementations for psoc-rs
//! HardFault handler using `defmt`
// Copyright (c) 2026, Infineon Technologies AG or an affiliate of Infineon Technologies AG.
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing permissions and
// limitations under the License.

#[repr(C)]
struct ExceptionFrame<'a> {
    sp: &'a cortex_m_rt::ExceptionFrame,
    r4: u32,
    r5: u32,
    r6: u32,
    r7: u32,
    r8: u32,
    r9: u32,
    r10: u32,
    r11: u32,
    nr: u32,
}

/// Hardfault handler.
///
/// Print a register dump and make a a semihosting-capable debug tool exit
/// with an error.
extern "C" fn unhandled_exception(frame: &ExceptionFrame) {
    defmt::println!("Unhandled exception:");
    defmt::println!(
        "  \
          r0: {:#010x}    r1: {:#010x}\n  \
          r2: {:#010x}    r3: {:#010x}\n  \
          r4: {:#010x}    r5: {:#010x}\n  \
          r6: {:#010x}    r7: {:#010x}\n  \
          r8: {:#010x}    r9: {:#010x}\n \
         r10: {:#010x}   r11: {:#010x}\n \
         r12: {:#010x}    sp: {:#010x}\n  \
          pc: {:#010x}    lr: {:#010x}\n\
        xpsr: {:#010x}   exc: {:#010x}",
        frame.sp.r0(),
        frame.sp.r1(),
        frame.sp.r2(),
        frame.sp.r3(),
        frame.r4,
        frame.r5,
        frame.r6,
        frame.r7,
        frame.r8,
        frame.r9,
        frame.r10,
        frame.r11,
        frame.sp.r12(),
        (frame.sp as *const _) as usize,
        frame.sp.pc(),
        frame.sp.lr(),
        frame.sp.xpsr(),
        frame.nr
    );
}

core::arch::global_asm!(
    "
        .cfi_sections .debug_frame
        .thumb_func
        .global HardFault, DefaultHandler
        .type DefaultHandler, %function
        .cfi_startproc
        HardFault:
        DefaultHandler:
            .cfi_offset xpsr, -4
            .cfi_offset pc, -8
            .cfi_offset lr, -12
            .cfi_offset r12, -16
            .cfi_offset r3, -20
            .cfi_offset r2, -24
            .cfi_offset r1, -28
            .cfi_offset r0, -32",

        #[cfg(core = "cm0")]
        "
            mov  r0, lr
            movs r1, #0x4
            tst  r0, r1
            mrs  r0, MSP
            beq  skip_psp
            mrs  r0, PSP
          skip_psp:

            mrs  r3, IPSR
            mov  r2, r11
            mov  r1, r10
            push {{r1, r2, r3}}

            mov  r3, r9
            mov  r2, r8
            push {{r2, r3}}

            push {{r0, r4, r5, r6, r7}}
        ",

        #[cfg(not(core = "cm0"))]
        "
            tst lr, 0x4
            ite eq
            mrseq r0, MSP
            mrsne r0, PSP
            mrs r12, IPSR
            stmfd sp!, {{r0, r4, r5, r6, r7, r8, r9, r10, r11, r12}}
        ",

        "
            .cfi_def_cfa_offset 72
            mov r0, sp
            bl {unhandled_exception}
            udf #0
        .cfi_endproc
        .size DefaultHandler, . - DefaultHandler
        ",
    unhandled_exception = sym unhandled_exception
);