| // **************************************************************************** |
| // semihost_hardfault.c |
| // - Provides hard fault handler to allow semihosting code not |
| // to hang application when debugger not connected. |
| // |
| // **************************************************************************** |
| // Copyright 2017-2018 NXP |
| // 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) |
| #if !defined (__SEMIHOST_HARDFAULT_DISABLE) |
| |
| __attribute__((naked)) |
| 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") ; |
| } |
| |
| #endif |
| |