From 0462f3b252d1208b496213f8fa36b65259e9e5a0 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Mon, 27 Apr 2020 09:56:19 +0300 Subject: [PATCH] Add simple exception handling This adds support for exception handling. It should provide simple and fast reporting of crucial info and full restoration without powering off. --- bootloader/exception_handlers.S | 233 +++++++++++++++++++++++++++++++ bootloader/link.ld | 1 + bootloader/main.c | 46 +++++- bootloader/start.S | 6 +- nyx/nyx_gui/exception_handlers.S | 233 +++++++++++++++++++++++++++++++ nyx/nyx_gui/link.ld | 1 + nyx/nyx_gui/nyx.c | 53 +++++++ nyx/nyx_gui/start.S | 10 +- 8 files changed, 574 insertions(+), 9 deletions(-) create mode 100644 bootloader/exception_handlers.S create mode 100644 nyx/nyx_gui/exception_handlers.S diff --git a/bootloader/exception_handlers.S b/bootloader/exception_handlers.S new file mode 100644 index 0000000..6b497a8 --- /dev/null +++ b/bootloader/exception_handlers.S @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2019 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Armv7tdmi Status register. + * + * bit0: Mode 0. + * bit1: Mode 1. + * bit2: Mode 2. + * bit3: Mode 3. + * bit4: Mode 4. + * bit5: Thumb state. + * bit6: FIQ disable. + * bit7: IRQ disable. + * bit8-27: Reserved. + * bit28: Overflow condition. + * bit29: Carry/Borrow/Extend condition. + * bit30: Zero condition. + * bit31: Negative/Less than condition. + * + * M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers + * 10000 | USER | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR + * 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq + * 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq + * 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc + * 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt + * 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und + * 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR + */ + +#define EXCP_EN_ADDR 0x4003FFFC +#define EXCP_TYPE_ADDR 0x4003FFF8 +#define EXCP_LR_ADDR 0x4003FFF4 + +#define EXCP_VEC_BASE 0x6000F000 +#define EVP_COP_RESET_VECTOR 0x200 +#define EVP_COP_UNDEF_VECTOR 0x204 +#define EVP_COP_SWI_VECTOR 0x208 +#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C +#define EVP_COP_DATA_ABORT_VECTOR 0x210 +#define EVP_COP_RSVD_VECTOR 0x214 +#define EVP_COP_IRQ_VECTOR 0x218 +#define EVP_COP_FIQ_VECTOR 0x21C + +#define MODE_USR 0x10 +#define MODE_FIQ 0x11 +#define MODE_IRQ 0x12 +#define MODE_SVC 0x13 +#define MODE_ABT 0x17 +#define MODE_UDF 0x1B +#define MODE_SYS 0x1F +#define MODE_MASK 0x1F + +#define FIQ 0x40 +#define IRQ 0x80 + +.section .text._irq_setup +.arm + +.extern ipl_main +.type ipl_main, %function + +.extern svc_handler +.type svc_handler, %function + +.extern irq_handler +.type irq_handler, %function + +.extern fiq_setup +.type fiq_setup, %function + +.extern fiq_handler +.type fiq_handler, %function + +.globl _irq_setup +.type _irq_setup, %function +_irq_setup: + MRS R0, CPSR + BIC R0, R0, #MODE_MASK /* Clear mode bits */ + ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */ + MSR CPSR, R0 + + /* Setup IRQ stack pointer */ + MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */ + LDR SP, =0x40040000 + + /* Setup SYS stack pointer */ + MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */ + LDR SP, =0x4003FF00 /* Will be changed later to DRAM */ + + MOV LR, PC + BL setup_vectors + /*BL fiq_setup*/ + + /* Enable interrupts */ + BL irq_enable_cpu_irq_exceptions + + B ipl_main + B . + +_reset: + LDR R0, =EXCP_EN_ADDR + LDR R1, =0x30505645 /* EVP0 */ + STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */ + LDR R0, =EXCP_LR_ADDR + MOV R1, LR + STR R1, [R0] /* Save LR in EXCP_LR_ADDR */ + LDR R0, =__bss_start + EOR R1, R1, R1 + LDR R2, =__bss_end + SUB R2, R2, R0 + BL memset + B _irq_setup + +_reset_handler: + LDR R0, =EXCP_TYPE_ADDR + LDR R1, =0x545352 /* RST */ + STR R1, [R0] /* RST in EXCP_TYPE_ADDR */ + B _reset + +_undefined_handler: + LDR R0, =EXCP_TYPE_ADDR + LDR R1, =0x464455 /* UDF */ + STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */ + B _reset + +_prefetch_abort_handler: + LDR R0, =EXCP_TYPE_ADDR + LDR R1, =0x54424150 /* PABT */ + STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */ + B _reset + +_data_abort_handler: + LDR R0, =EXCP_TYPE_ADDR + LDR R1, =0x54424144 /* DABT */ + STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */ + B _reset + +.globl irq_enable_cpu_irq_exceptions +.type irq_enable_cpu_irq_exceptions, %function +irq_enable_cpu_irq_exceptions: + MRS R12, CPSR + BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */ + MSR CPSR, R12 + BX LR + +.globl irq_disable_cpu_irq_exceptions +.type irq_disable_cpu_irq_exceptions, %function +irq_disable_cpu_irq_exceptions: + MRS R12, CPSR + ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */ + MSR CPSR, R12 + BX LR + +_irq_handler: + MOV R13, R0 /* Save R0 in R13_IRQ */ + SUB R0, LR, #4 /* Put return address in R0_SYS */ + MOV LR, R1 /* Save R1 in R14_IRQ (LR) */ + MRS R1, SPSR /* Put the SPSR in R1_SYS */ + + MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */ + STMFD SP!, {R0, R1} /* SPSR and PC */ + STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */ + MOV R0, SP /* Make SP_SYS visible to IRQ mode */ + SUB SP, SP, #8 /* Make room for stacking R0 and R1 */ + + MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */ + STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */ + + MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */ + LDR R12, =irq_handler + MOV LR, PC /* Copy the return address to link register */ + BX R12 /* Call the C IRQ handler (ARM/THUMB) */ + + MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */ + MOV R0, SP /* Make SP_SYS visible to IRQ mode */ + ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */ + + MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */ + MOV SP, R0 /* Copy SP_SYS to SP_IRQ */ + LDR R0, [SP, #28] /* Load the saved SPSR from the stack */ + MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */ + + LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */ + NOP /* Cant access barked registers immediately */ + LDR LR, [SP, #24] /* Load return address from the SYS stack */ + MOVS PC, LR /* Return restoring CPSR from SPSR */ + +_fiq_handler: + BL fiq_handler + +setup_vectors: + /* Setup vectors */ + LDR R0, =EXCP_VEC_BASE + + LDR R1, =_reset_handler + STR R1, [R0, #EVP_COP_RESET_VECTOR] + + LDR R1, =_undefined_handler + STR R1, [R0, #EVP_COP_UNDEF_VECTOR] + + LDR R1, =_reset_handler + STR R1, [R0, #EVP_COP_SWI_VECTOR] + + LDR R1, =_prefetch_abort_handler + STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR] + + LDR R1, =_data_abort_handler + STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR] + + LDR R1, =_reset_handler + STR R1, [R0, #EVP_COP_RSVD_VECTOR] + + LDR R1, =_irq_handler + STR R1, [R0, #EVP_COP_IRQ_VECTOR] + + LDR R1, =_fiq_handler + STR R1, [R0, #EVP_COP_FIQ_VECTOR] + + BX LR diff --git a/bootloader/link.ld b/bootloader/link.ld index 85568dd..cd8b8a1 100644 --- a/bootloader/link.ld +++ b/bootloader/link.ld @@ -7,6 +7,7 @@ SECTIONS { *(.text._start); *(._boot_cfg); *(._ipl_version); + *(.text._irq_setup); *(.text*); } .data : { diff --git a/bootloader/main.c b/bootloader/main.c index 6f4c263..054b97e 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -1182,8 +1182,24 @@ static void _patched_rcm_protection() sdmmc_storage_end(&storage); } +#define EXCP_EN_ADDR 0x4003FFFC +#define EXCP_MAGIC 0x30505645 // EVP0 +#define EXCP_TYPE_ADDR 0x4003FFF8 +#define EXCP_TYPE_RESET 0x545352 // RST +#define EXCP_TYPE_UNDEF 0x464455 // UDF +#define EXCP_TYPE_PABRT 0x54424150 // PABT +#define EXCP_TYPE_DABRT 0x54424144 // DABT +#define EXCP_LR_ADDR 0x4003FFF4 + static void _show_errors() { + u32 *excp_enabled = (u32 *)EXCP_EN_ADDR; + u32 *excp_type = (u32 *)EXCP_TYPE_ADDR; + u32 *excp_lr = (u32 *)EXCP_LR_ADDR; + + if (*excp_enabled == EXCP_MAGIC) + h_cfg.errors |= ERR_EXCEPT_ENB; + if (h_cfg.errors) { gfx_clear_grey(0x1B); @@ -1195,7 +1211,35 @@ static void _show_errors() if (h_cfg.errors & ERR_SYSOLD_MTC) WPRINTF("Missing or old Minerva library!\n"); - WPRINTF("\nUpdate your bootloader folder!\n\n"); + if (h_cfg.errors & ~ERR_EXCEPT_ENB) + { + WPRINTF("\nUpdate your bootloader folder!\n\n"); + } + + if (h_cfg.errors & ERR_EXCEPT_ENB) + { + WPRINTFARGS("An exception happened (LR %08X):\n", *excp_lr); + switch (*excp_type) + { + case EXCP_TYPE_RESET: + WPRINTF("Reset"); + break; + case EXCP_TYPE_UNDEF: + WPRINTF("Undefined instruction"); + break; + case EXCP_TYPE_PABRT: + WPRINTF("Prefetch abort"); + break; + case EXCP_TYPE_DABRT: + WPRINTF("Data abort"); + break; + } + WPRINTF("\n"); + + // Clear the exception. + *excp_enabled = 0; + } + WPRINTF("Press any key..."); msleep(2000); diff --git a/bootloader/start.S b/bootloader/start.S index 534f963..269f2c7 100644 --- a/bootloader/start.S +++ b/bootloader/start.S @@ -23,8 +23,8 @@ .extern memset .type memset, %function -.extern ipl_main -.type ipl_main, %function +.extern _irq_setup +.type _irq_setup, %function .globl _start .type _start, %function @@ -67,7 +67,7 @@ _real_start: LDR R2, =__bss_end SUB R2, R2, R0 BL memset - BL ipl_main + BL _irq_setup B . .globl pivot_stack diff --git a/nyx/nyx_gui/exception_handlers.S b/nyx/nyx_gui/exception_handlers.S new file mode 100644 index 0000000..6b497a8 --- /dev/null +++ b/nyx/nyx_gui/exception_handlers.S @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2019 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * Armv7tdmi Status register. + * + * bit0: Mode 0. + * bit1: Mode 1. + * bit2: Mode 2. + * bit3: Mode 3. + * bit4: Mode 4. + * bit5: Thumb state. + * bit6: FIQ disable. + * bit7: IRQ disable. + * bit8-27: Reserved. + * bit28: Overflow condition. + * bit29: Carry/Borrow/Extend condition. + * bit30: Zero condition. + * bit31: Negative/Less than condition. + * + * M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers + * 10000 | USER | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR + * 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq + * 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq + * 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc + * 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt + * 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und + * 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR + */ + +#define EXCP_EN_ADDR 0x4003FFFC +#define EXCP_TYPE_ADDR 0x4003FFF8 +#define EXCP_LR_ADDR 0x4003FFF4 + +#define EXCP_VEC_BASE 0x6000F000 +#define EVP_COP_RESET_VECTOR 0x200 +#define EVP_COP_UNDEF_VECTOR 0x204 +#define EVP_COP_SWI_VECTOR 0x208 +#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C +#define EVP_COP_DATA_ABORT_VECTOR 0x210 +#define EVP_COP_RSVD_VECTOR 0x214 +#define EVP_COP_IRQ_VECTOR 0x218 +#define EVP_COP_FIQ_VECTOR 0x21C + +#define MODE_USR 0x10 +#define MODE_FIQ 0x11 +#define MODE_IRQ 0x12 +#define MODE_SVC 0x13 +#define MODE_ABT 0x17 +#define MODE_UDF 0x1B +#define MODE_SYS 0x1F +#define MODE_MASK 0x1F + +#define FIQ 0x40 +#define IRQ 0x80 + +.section .text._irq_setup +.arm + +.extern ipl_main +.type ipl_main, %function + +.extern svc_handler +.type svc_handler, %function + +.extern irq_handler +.type irq_handler, %function + +.extern fiq_setup +.type fiq_setup, %function + +.extern fiq_handler +.type fiq_handler, %function + +.globl _irq_setup +.type _irq_setup, %function +_irq_setup: + MRS R0, CPSR + BIC R0, R0, #MODE_MASK /* Clear mode bits */ + ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */ + MSR CPSR, R0 + + /* Setup IRQ stack pointer */ + MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */ + LDR SP, =0x40040000 + + /* Setup SYS stack pointer */ + MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */ + LDR SP, =0x4003FF00 /* Will be changed later to DRAM */ + + MOV LR, PC + BL setup_vectors + /*BL fiq_setup*/ + + /* Enable interrupts */ + BL irq_enable_cpu_irq_exceptions + + B ipl_main + B . + +_reset: + LDR R0, =EXCP_EN_ADDR + LDR R1, =0x30505645 /* EVP0 */ + STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */ + LDR R0, =EXCP_LR_ADDR + MOV R1, LR + STR R1, [R0] /* Save LR in EXCP_LR_ADDR */ + LDR R0, =__bss_start + EOR R1, R1, R1 + LDR R2, =__bss_end + SUB R2, R2, R0 + BL memset + B _irq_setup + +_reset_handler: + LDR R0, =EXCP_TYPE_ADDR + LDR R1, =0x545352 /* RST */ + STR R1, [R0] /* RST in EXCP_TYPE_ADDR */ + B _reset + +_undefined_handler: + LDR R0, =EXCP_TYPE_ADDR + LDR R1, =0x464455 /* UDF */ + STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */ + B _reset + +_prefetch_abort_handler: + LDR R0, =EXCP_TYPE_ADDR + LDR R1, =0x54424150 /* PABT */ + STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */ + B _reset + +_data_abort_handler: + LDR R0, =EXCP_TYPE_ADDR + LDR R1, =0x54424144 /* DABT */ + STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */ + B _reset + +.globl irq_enable_cpu_irq_exceptions +.type irq_enable_cpu_irq_exceptions, %function +irq_enable_cpu_irq_exceptions: + MRS R12, CPSR + BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */ + MSR CPSR, R12 + BX LR + +.globl irq_disable_cpu_irq_exceptions +.type irq_disable_cpu_irq_exceptions, %function +irq_disable_cpu_irq_exceptions: + MRS R12, CPSR + ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */ + MSR CPSR, R12 + BX LR + +_irq_handler: + MOV R13, R0 /* Save R0 in R13_IRQ */ + SUB R0, LR, #4 /* Put return address in R0_SYS */ + MOV LR, R1 /* Save R1 in R14_IRQ (LR) */ + MRS R1, SPSR /* Put the SPSR in R1_SYS */ + + MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */ + STMFD SP!, {R0, R1} /* SPSR and PC */ + STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */ + MOV R0, SP /* Make SP_SYS visible to IRQ mode */ + SUB SP, SP, #8 /* Make room for stacking R0 and R1 */ + + MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */ + STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */ + + MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */ + LDR R12, =irq_handler + MOV LR, PC /* Copy the return address to link register */ + BX R12 /* Call the C IRQ handler (ARM/THUMB) */ + + MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */ + MOV R0, SP /* Make SP_SYS visible to IRQ mode */ + ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */ + + MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */ + MOV SP, R0 /* Copy SP_SYS to SP_IRQ */ + LDR R0, [SP, #28] /* Load the saved SPSR from the stack */ + MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */ + + LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */ + NOP /* Cant access barked registers immediately */ + LDR LR, [SP, #24] /* Load return address from the SYS stack */ + MOVS PC, LR /* Return restoring CPSR from SPSR */ + +_fiq_handler: + BL fiq_handler + +setup_vectors: + /* Setup vectors */ + LDR R0, =EXCP_VEC_BASE + + LDR R1, =_reset_handler + STR R1, [R0, #EVP_COP_RESET_VECTOR] + + LDR R1, =_undefined_handler + STR R1, [R0, #EVP_COP_UNDEF_VECTOR] + + LDR R1, =_reset_handler + STR R1, [R0, #EVP_COP_SWI_VECTOR] + + LDR R1, =_prefetch_abort_handler + STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR] + + LDR R1, =_data_abort_handler + STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR] + + LDR R1, =_reset_handler + STR R1, [R0, #EVP_COP_RSVD_VECTOR] + + LDR R1, =_irq_handler + STR R1, [R0, #EVP_COP_IRQ_VECTOR] + + LDR R1, =_fiq_handler + STR R1, [R0, #EVP_COP_FIQ_VECTOR] + + BX LR diff --git a/nyx/nyx_gui/link.ld b/nyx/nyx_gui/link.ld index f0f01a0..bdf3dc0 100644 --- a/nyx/nyx_gui/link.ld +++ b/nyx/nyx_gui/link.ld @@ -6,6 +6,7 @@ SECTIONS { .text : { *(.text._start); *(._ipl_version); + *(.text._irq_setup); *(.text*); } .data : { diff --git a/nyx/nyx_gui/nyx.c b/nyx/nyx_gui/nyx.c index d7b0e60..b3970bd 100644 --- a/nyx/nyx_gui/nyx.c +++ b/nyx/nyx_gui/nyx.c @@ -367,6 +367,59 @@ void load_saved_configuration() } } +#define EXCP_EN_ADDR 0x4003FFFC +#define EXCP_MAGIC 0x30505645 // EVP0 +#define EXCP_TYPE_ADDR 0x4003FFF8 +#define EXCP_TYPE_RESET 0x545352 // RST +#define EXCP_TYPE_UNDEF 0x464455 // UDF +#define EXCP_TYPE_PABRT 0x54424150 // PABT +#define EXCP_TYPE_DABRT 0x54424144 // DABT +#define EXCP_LR_ADDR 0x4003FFF4 + +static void _show_errors() +{ + u32 *excp_enabled = (u32 *)EXCP_EN_ADDR; + u32 *excp_type = (u32 *)EXCP_TYPE_ADDR; + u32 *excp_lr = (u32 *)EXCP_LR_ADDR; + + if (*excp_enabled == EXCP_MAGIC) + { + gfx_clear_grey(0); + gfx_con_setpos(0, 0); + display_backlight_brightness(100, 1000); + + WPRINTFARGS("An exception happened (LR %08X):\n", *excp_lr); + switch (*excp_type) + { + case EXCP_TYPE_RESET: + WPRINTF("Reset"); + break; + case EXCP_TYPE_UNDEF: + WPRINTF("Undefined instruction"); + break; + case EXCP_TYPE_PABRT: + WPRINTF("Prefetch abort"); + break; + case EXCP_TYPE_DABRT: + WPRINTF("Data abort"); + break; + } + WPRINTF("\n"); + + // Clear the exception. + *excp_lr = 0; + *excp_type = 0; + *excp_enabled = 0; + + WPRINTF("Press any key..."); + + msleep(2000); + btn_wait(); + + reload_nyx(); + } +} + void nyx_init_load_res() { bpmp_mmu_enable(); diff --git a/nyx/nyx_gui/start.S b/nyx/nyx_gui/start.S index c520ef1..20ff5cb 100644 --- a/nyx/nyx_gui/start.S +++ b/nyx/nyx_gui/start.S @@ -23,8 +23,8 @@ .extern memset .type memset, %function -.extern ipl_main -.type ipl_main, %function +.extern _irq_setup +.type _irq_setup, %function .globl _start .type _start, %function @@ -36,7 +36,7 @@ _start: /* If we are not in the right location already, copy a relocator to upper IRAM. */ ADR R2, _reloc_ipl - LDR R3, =0x4003FFE0 + LDR R3, =0x4003FF00 MOV R4, #(_real_start - _reloc_ipl) _copy_loop: LDMIA R2!, {R5} @@ -48,7 +48,7 @@ _copy_loop: LDR R2, =__ipl_end SUB R2, R2, R1 LDR R3, =_real_start - LDR R4, =0x4003FFE0 + LDR R4, =0x4003FF00 BX R4 _reloc_ipl: @@ -67,7 +67,7 @@ _real_start: LDR R2, =__bss_end SUB R2, R2, R0 BL memset - BL ipl_main + BL _irq_setup B . .globl pivot_stack