path: root/source/semihost_hardfault.c
diff options
Diffstat (limited to 'source/semihost_hardfault.c')
1 files changed, 109 insertions, 0 deletions
diff --git a/source/semihost_hardfault.c b/source/semihost_hardfault.c
new file mode 100644
index 0000000..dc8d3ae
--- /dev/null
+++ b/source/semihost_hardfault.c
@@ -0,0 +1,109 @@
+// ****************************************************************************
+// semihost_hardfault.c
+// - Provides hard fault handler to allow semihosting code not
+// to hang application when debugger not connected.
+// ****************************************************************************
+// Copyright(C) NXP Semiconductors, 2017-2018
+// All rights reserved.
+// Software that is described herein is for illustrative purposes only
+// which provides customers with programming information regarding the
+// NXP Cortex-M based MCUs. This software is supplied "AS IS" without any
+// warranties of any kind, and NXP Semiconductors and its licensor disclaim any
+// and all warranties, express or implied, including all implied warranties of
+// merchantability, fitness for a particular purpose and non-infringement of
+// intellectual property rights. NXP Semiconductors assumes no responsibility
+// or liability for the use of the software, conveys no license or rights under
+// any patent, copyright, mask work right, or any other intellectual property
+// rights in or to any products. NXP Semiconductors reserves the right to make
+// changes in the software without notification. NXP Semiconductors also makes
+// no representation or warranty that such application will be suitable for the
+// specified use without further testing or modification.
+// Permission to use, copy, modify, and distribute this software and its
+// documentation is hereby granted, under NXP Semiconductors' and its
+// licensor's relevant copyrights in the software, without fee, provided that it
+// is used in conjunction with NXP Semiconductors microcontrollers. This
+// copyright, permission, and disclaimer notice must appear in all copies of
+// this code.
+// ****************************************************************************
+// ===== DESCRIPTION =====
+// One of the issues with applications that make use of semihosting operations
+// (such as printf calls) is that the code will not execute correctly when the
+// debugger is not connected. Generally this will show up with the application
+// appearing to just hang. This may include the application running from reset
+// or powering up the board (with the application already in FLASH), and also
+// as the application failing to continue to execute after a debug session is
+// terminated.
+// The problem here is that the "bottom layer" of the semihosted variants of
+// the C library, semihosting is implemented by a "BKPT 0xAB" instruction.
+// When the debug tools are not connected, this instruction triggers a hard
+// fault - and the default hard fault handler within an application will
+// typically just contains an infinite loop - causing the application to
+// appear to have hang when no debugger is connected.
+// The below code provides an example hard fault handler which instead looks
+// to see what the instruction that caused the hard fault was - and if it
+// was a "BKPT 0xAB", then it instead returns back to the user application.
+// In most cases this will allow applications containing semihosting
+// operations to execute (to some degree) when the debugger is not connected.
+// == NOTE ==
+// Correct execution of the application containing semihosted operations
+// which are vectored onto this hard fault handler cannot be guaranteed. This
+// is because the handler may not return data or return codes that the higher
+// level C library code or application code expects. This hard fault handler
+// is meant as a development aid, and it is not recommended to leave
+// semihosted code in a production build of your application!
+// ****************************************************************************
+// Allow handler to be removed by setting a define (via command line)
+void HardFault_Handler(void){
+ __asm( ".syntax unified\n"
+ // Check which stack is in use
+ "MOVS R0, #4 \n"
+ "MOV R1, LR \n"
+ "TST R0, R1 \n"
+ "BEQ _MSP \n"
+ "MRS R0, PSP \n"
+ "B _process \n"
+ "_MSP: \n"
+ "MRS R0, MSP \n"
+ // Load the instruction that triggered hard fault
+ "_process: \n"
+ "LDR R1,[R0,#24] \n"
+ "LDRH R2,[r1] \n"
+ // Semihosting instruction is "BKPT 0xAB" (0xBEAB)
+ "LDR R3,=0xBEAB \n"
+ "CMP R2,R3 \n"
+ "BEQ _semihost_return \n"
+ // Wasn't semihosting instruction so enter infinite loop
+ "B . \n"
+ // Was semihosting instruction, so adjust location to
+ // return to by 1 instruction (2 bytes), then exit function
+ "_semihost_return: \n"
+ "ADDS R1,#2 \n"
+ "STR R1,[R0,#24] \n"
+ // Set a return value from semihosting operation.
+ // 32 is slightly arbitrary, but appears to allow most
+ // C Library IO functions sitting on top of semihosting to
+ // continue to operate to some degree
+ "MOVS R1,#32 \n"
+ "STR R1,[ R0,#0 ] \n" // R0 is at location 0 on stack
+ // Return from hard fault handler to application
+ "BX LR \n"
+ ".syntax divided\n") ;

X-ray Engineering Services