ThunderBench For ARM Knowledgebase & FAQ

General
Installation
License & Activation
Project Explorer
Project Builder
Compiler
Linker
Debugger
Troubleshooting

Browse the Knowledgebase:

1) Click on each category to left of this section, you can browse that catagory

2) In any category or where the search button is visible, you can seach for a keyword or a short phrase. 

3) The Search Exact button, returns Q&A with the exact shortphrase either in the Q or the A.
The Search Relaxed returns either keyword in your short phrase whether in Q or A.

4) The Search TechNote returns Q&A with the exact TEch Note Number usually displayed at the end of the question.

 

For assistance please contact support .

 

To install Trials generally a 30 days or 60 days trial period, or a time-expired trial, please follow these steps:

- Download the desired ThunderBench from our website, in Download Trials.
- Click on the .exe/.zip file downloaded, Agree with the license and follow the prompt.
- When asked about the destination folder on your C drive, please accept default (recommended) or choose your own destination path.
- Please follow the prompt from this point on, you can use all defaults until Finish.

How to activate:

- When you are ready to purchase a license, upon startup on ThunderBench, please click the ACTIVATE button, and note down the Host ID a.k.a Machine ID.
- Contact our sales to purchase ThunderBench, our sales team will ask for the Host ID and they will reply back with a pair of numbers:
1- Your Serial Number
2- Your Activation key Code
Come back to the same place and hit activate again, and enter both numbers in their respective fields, when activated the product will no longer be in Trial Mode.

Notes:  none.

For assistance please contact support .

 

Often when you start debugging you end up in the Hard_Fault() Interrupt Routine, or some call it Default_Vector(). This is because the Hard Fault interrupt has been triggered which means something not right in your application, common reasons are an illegal instruction has been executed, or the PC has been set to an invalid address.

Here is a quick Checklist the user must run through to determine if your ARM application is well integrated.

  1. Check the linker file, if it is valid and the address of FLASH and RAM are correct.
  2. Try to single step into the code before you reach the Hard_fault() interrupt, you need to do that multiple times to zoom into the code preceding the Hard_fault(), then switch to the Disassembly view to single step into the assembly instructions to determine which instruction is causing the Hard_fault(). In most cases and most common reason is that it is an ARM instruction in Thumb mode. Remember that the Cortex series is all Thumb.
  3. If #2 is detected, then check if you are linking any library that was compiled fro ARM while you are using a Cortex core.
  4. Check for unhandled interrupts like Systick or Timers etc.. Maybe you enabled these interrupts but you did not have any ISR to respond to these interrupt, in this case the Default_Interrupt() will kick in and in most case it is the Hard_fault() interrupt.
  5. Hard_fault() is mainly an application issue and not a bad hardware
  6. Inspect the startup code, the system file (which has sysinit), and try to break on the Reset_Handler (reset vector) , then single step from there onward. This is one of the reason that default debugger init script sets a Breakpoint on the Reset_Handler(), and another Breakpoint on the user main(); To make sure that the application has been loaded properly and the reset vector is intact. Most problems are in between the Reset_Handler and the user main();
  7. When you are in disassembly view, and single stepping, watch if you jump to a library routine and the address of this library is in an illegal memory region.
  8. If you plan on using full context library routines like sprintf() and printf(), remember those are RAM memory intensive and stack intensive functions. It is only common sense to limit the usage of these heavy string routines, because they are slow and heavy. ThunderBench by default loads the nano library which contains a smaller footprint of these library function (with limitation, mainly no floating point support). If this is your case, then maybe the Hard_Fault() is due to the usage of these routines.

For assistance please contact support .

 

The ARM Cortex-M core implements a set of fault exceptions. Each exception relates to an error condition. If the error occurs, the ARM Cortex-M core stops executing the current instruction, and branches to the exception's handler function. The standard CMSIS names for the Fault Handlers are:

• HardFault_Handler()   (Most Common or some call it default_handler() )
• UsageFault_Handler()
• BusFault_Handler()
• MemMang_Handler()

The reasons under which the ARM Cortex-M core calls each of these handlers is out of scope of this document, please refer to ARM Cortex-M documentation from ARM, or web resources. For the purpose of this document it is enough to say that, if your application ends up in one of these handlers, then something has gone wrong. We will focus in this document on the Hard faults which  are the most common fault type, if  other fault types are not enabled individually they will end up being hard faults.

Debugging a ARM Cortex-M Hard Fault
The stack frame of the fault handler contains the state of the ARM Cortex-M registers at the time that the fault occurred. The code below shows how to read the register values from the stack into C variables. Once this is done, the values of the variables can be inspected in a debugger just as an other variable.

Hint: You can inspect these variables by opening the Variables view in the debugger, when a  HardFault_Handler()  occurs it enters a function called prvGetRegistersFromStack() with local variables that will be automatically displayed in the Variables view. Or as an alternative, just hover the mouse over any of these Global C variables to get their value

First, a very short assembly function is defined inside the HardFault_Handler() ISR to determine which stack was being used when the fault occurred. Once this is done, the fault handler assembly code passes a pointer to the stack into a C function called prvGetRegistersFromStack().

The fault handler is shown below using GCC syntax. Note that the function is declared as being naked, so it does not contain any compiler generated code (hence, there is no function entry prologue code).

/* The prototype shows it is a naked function - in effect this is just an assembly function. */
static void HardFault_Handler( void ) __attribute__( ( naked ) );

/* The fault handler implementation calls a function called prvGetRegistersFromStack(). */

static void HardFault_Handler(void)
{
__asm volatile
(
" tst lr, #4 n"
" ite eq n"
" mrseq r0, msp n"
" mrsne r0, psp n"
" ldr r1, [r0, #24] n"
" ldr r2, handler2_address_const n"
" bx r2 n"
" handler2_address_const: .word prvGetRegistersFromStack n"
);
}


The implementation of prvGetRegistersFromStack() is shown below. prvGetRegistersFromStack() copies the register values from the stack into the C variables, then sits in a loop. The variables are named to indicate the register value that they hold. Other registers will not have changed since the fault occurred, and can be viewed directly in the debugger's CPU register window.

void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
{
/* These are volatile to try and prevent the compiler/linker optimising them away. If the debugger won't show the values of the variables */

/* make them as global. In the Variables View click on the "glasses" icon and add these variables to the view for inspection. */


volatile uint32_t r0;
volatile uint32_t r1;
volatile uint32_t r2;
volatile uint32_t r3;
volatile uint32_t r12;
volatile uint32_t lr; /* Link register. */
volatile uint32_t pc; /* Program counter. */
volatile uint32_t psr;/* Program status register. */

r0 = pulFaultStackAddress[ 0 ];
r1 = pulFaultStackAddress[ 1 ];
r2 = pulFaultStackAddress[ 2 ];
r3 = pulFaultStackAddress[ 3 ];

r12 = pulFaultStackAddress[ 4 ];
lr = pulFaultStackAddress[ 5 ];
pc = pulFaultStackAddress[ 6 ];
psr = pulFaultStackAddress[ 7 ];

/* When the following line is hit, the variables contain the register values. */
for( ;; );
}


Inspecting the Hard Fault Stack Registers Values
The first register of interest is the program counter. In the code above, the variable pc contains the program counter value. pc holds the address of the instruction that was executing when the hard fault (or other fault) occurred. To find the instruction at the address held in the pc variable, please do:

1. Open an assembly code window in the debugger, and manually enter the address to view the assembly instructions at that address, OR
2. Open the break point window in the debugger, and manually define an execution or access break point at that address. With the break point set, restart the application to see which line of code the instruction relates to and caused the Hard Fault.

Knowing the instruction that was being executed when the fault occurred allows you to know which other register values are also of interest. For example, if the instruction was using the value of R7 as an address, then the value of R7 needs to be known. Further, examining the assembly code, and the C code that generated the assembly code, will show what R7 actually holds (it might be the value of a variable, or other).

 

For assistance please contact support .

 

All tools setting are found conveniently in one place. Please highlight the project name and click on tools "C/C++ Build Settings For Project...) in the toolbar.

Target Setup TAB
If you are not using one of ThunderBench wizards to import or create a project, the Target Setup will help you define your Target and setup your project to accommodate your desired ARM target.

  1. Pick a chip vendor
  2. Select a microcontroller
  3. Choose the code location either FLASH or RAM

Hint: what this wizard does is setup the proper CORE of your Target, and setup the proper memory map for it used by the linker as defined in ThunderBench Targets Database.

Tools Settings TAB

Global Target Options:

1. Target Processor:

  • Core Processor: This is the core of your target, please pick one of the listed core. If you used any ThunderBench project wizards, this options is automatically set for you following the target information database. Permissible names are: ‘arm2’, ‘arm250’, ‘arm3’, ‘arm6’, ‘arm60’, ‘arm600’, ‘arm610’, ‘arm620’, ‘arm7’, ‘arm7m’, ‘arm7d’, ‘arm7dm’, ‘arm7di’, ‘arm7dmi’, ‘arm70’, ‘arm700’, ‘arm700i’, ‘arm710’, ‘arm710c’, ‘arm7100’, ‘arm720’, ‘arm7500’, ‘arm7500fe’, ‘arm7tdmi’, ‘arm7tdmi-s’, ‘arm710t’, ‘arm720t’, ‘arm740t’, ‘strongarm’, ‘strongarm110’, ‘strongarm1100’, ‘strongarm1110’, ‘arm8’, ‘arm810’, ‘arm9’, ‘arm9e’, ‘arm920’, ‘arm920t’, ‘arm922t’, ‘arm946e-s’, ‘arm966e-s’, ‘arm968e-s’, ‘arm926ej-s’, ‘arm940t’, ‘arm9tdmi’, ‘arm10tdmi’, ‘arm1020t’, ‘arm1026ej-s’, ‘arm10e’, ‘arm1020e’, ‘arm1022e’, ‘arm1136j-s’, ‘arm1136jf-s’, ‘mpcore’, ‘mpcorenovfp’, ‘arm1156t2-s’, ‘arm1156t2f-s’, ‘arm1176jz-s’, ‘arm1176jzf-s’, ‘cortex-a5’, ‘cortex-a7’, ‘cortex-a8’, ‘cortex-a9’, ‘cortex-a15’, ‘cortex-a53’, ‘cortex-r4’, ‘cortex-r4f’, ‘cortex-r5’, ‘cortex-r7’, ‘cortex-m4’, ‘cortex-m3’, ‘cortex-m1’, ‘cortex-m0’, ‘cortex-m0plus’, ‘marvell-pj4’, ‘xscale’, ‘iwmmxt’, ‘iwmmxt2’, ‘ep9312’, ‘fa526’, ‘fa626’, ‘fa606te’, ‘fa626te’, ‘fmp626’, ‘fa726te’.
  • Thumb: Please click if you want to generate thumb instruction (default for all cortex targets), if unclicked the compiler will generate full ARM instructions.
  • Thumb Interwork: Generate code that supports calling between the ARM and Thumb instruction sets. Without this option, on pre-v5 architectures, the two instruction sets cannot be reliably used inside one program. The default is -mno-thumb-interwork, since slightly larger code is generated when -mthumb-interwork is specified. In AAPCS configurations this option is meaningless.
  • Endiannes: Specify whether Little or Big Endian, default is Little Endian that covers most ARM targets and it is the default for all Cortex Cores.
  • Float ABI: Specifies which floating-point ABI to use. Permissible values are: ‘soft’, ‘softfp’ and ‘hard’. Specifying ‘soft’ causes the compiler to generate output containing library calls for floating-point operations. ‘softfp’ allows the generation of code using hardware floating-point instructions, but still uses the soft-float calling conventions. ‘hard’ allows generation of floating-point instructions and uses FPU-specific calling conventions.The default depends on the specific target configuration. Note that the hard-float and soft-float ABIs are not link-compatible; you must compile your entire program with the same ABI, and link with a compatible set of libraries. The default is soft and that covers all ARM targets. To use hard you must have an FPU inside your target.
  • FPU Type: This specifies what floating-point hardware (or hardware emulation) is available on the target. Permissible names are: ‘vfp’, ‘vfpv3’, ‘vfpv3-fp16’, ‘vfpv3-d16’, ‘vfpv3-d16-fp16’, ‘vfpv3xd’, ‘vfpv3xd-fp16’, ‘neon’, ‘neon-fp16’, ‘vfpv4’, ‘vfpv4-d16’, ‘fpv4-sp-d16’, ‘neon-vfpv4’, ‘fp-armv8’, ‘neon-fp-armv8’, and ‘crypto-neon-fp-armv8’. If -msoft-float is specified this specifies the format of floating-point values.If the selected floating-point hardware includes the NEON extension (e.g. -mfpu=‘neon’), note that floating-point operations are not generated by GCC's auto-vectorization pass unless -funsafe-math-optimizations is also specified. This is because NEON hardware does not fully implement the IEEE 754 standard for floating-point arithmetic (in particular denormal values are treated as zero), so the use of NEON instructions may lead to a loss of precision.

2. Debugging:

  • Debug Level: Default is g3 for maximum debugging visibility.
  • Debug Format: Default is dwarf-2 compatible with the debugger.
  • Other debugging flags: extra command line option you might pass to the debugger. Not commonly used.

3. Additional Tools

  • Create Flash Image (.bin): Create a secondary output file by default ThunderBench create the .elf file for debugging with C and Assembly source and a secondary pure binary output file .bin to use with any flash programming to program your device (wihtout debugging) or for production purpose, or for sharing your application with others without sharing the source.
  • Create Extended Listing: Creates a .lst file for every .C file, where you have the assembly generated for the C code in that file.
  • Output Project Size Flash and Data: At the end of the build the tools will output in the console view the Flash (code) size in bytes, and the data (RAM) size allocated plus the total Flash +RAM.

Thunder ARM C/C++ Compiler Options:

1. Sumamry page (C/C++ compiler option)

  • Summary Page: This page is for information only, it states the path of the active compiler, and a collection of all options used and passed to the compiler, and the command line pattern. Not commonly used or modified. Please use defaults.

1. Preprocessor

  • Do not search system directories: Do not search the standard system directories for header files. Only the directories you have specified with '-I' options (and the directory of the current file, if appropriate) are searched
  • Preprocessor only: Stop after the preprocessing stage; do not run the compiler. The output is in the form of preprocessed source code, which is sent to the standard output. Input files which don't require preprocessing are ignored.
  • Defined Symbols: Define Symbols that are used inside the code with ifdef directives to control the compilation of the code. Example:
    My_Symbol=1 or My_Symbol. Both formats define My_Symbol as true or 1.
  • Undefine symbols: It will undefine symbols previously Defined. This is used if you want to temporary undefine a symbol without removing it from the list.

2. Directories

  • Include Paths: Add the directory to the list of directories to be searched for header files. Directories named by '-I' are searched before the standard system include directories. If the directory is a standard system include directory, the option is ignored to ensure that the default search order for system directories and the special treatment of system headers are not defeated. You can pick folders from the workspace or from the file system. Commonly you include folders from your project where you want the compiler to search for the included header files.

3. Optimization

  • Optimization level:

    -O0 (NONE) Do not optimize. This is the default.

    -Os Optimize for size. '-Os' enables all '-O2' optimizations that do not typically increase code size. It also performs further optimizations designed to reduce code size. '-Os' disables the following optimization flags: -falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -fprefetch-loop-arrays (Commonly used)

    -O1 : With '-O1', the compiler tries to reduce code size and execution time, without performing any optimizations that take a great deal of compilation time. It turns on the following optimization flags: -fdefer-pop -fmerge-constants -fthread-jumps -floop-optimize -fcrossjumping -fif-conversion -fif-conversion2 -fdelayed-branch -fguess-branch-probability -fcprop-registers it also turns on '-fomit-frame-pointer' on machines where doing so does not interfere with debugging.

    -O2:  Optimize even more. The compiler performs nearly all supported optimizations that do not involve a space-speed tradeoff. The compiler does not perform loop unrolling or function inlining when you specify '-O2'. As compared to '-O1', this option increases both compilation time and the performance of the generated code. '-O2' turns on all optimization flags specified by '-O1'. It also turns on the following optimization flags: -fforce-mem -foptimize-sibling-calls -fstrength-reduce -fcse-follow-jumps -fcse-skip-blocks -frerun-cse-after-loop -frerun-loop-opt -fgcse -fgcse-lm -fgcse-sm -fdelete-null-pointer-checks -fexpensive-optimizations -fregmove -fschedule-insns -fschedule-insns2 -fsched-interblock -fsched-spec -fcaller-saves -fpeephole2 -freorder-blocks -freorder-functions -fstrict-aliasing -falign-functions -falign-jumps -falign-loops -falign-labels
    Please note the warning under '-fgcse' about invoking '-O2' on programs that use computed gotos.

    -O3 Optimize yet more. '-O3' turns on all optimizations specified by '-O2' and also turns on the '-finline-functions' and '-frename-registers' options.

  • Pack structure: Pack all structure members together without holes. Please use with care and test your application.

  • Short enumarations Allocate to an enum type only as many bytes as it needs for the declared range of possible values. Specifically, the enum type will be equivalent to the smallest integer type which has enough room. Please use with care and test your application.

  • Function sections/Data Sections : Place each function or data item into its own section in the output file if the target supports arbitrary sections. The name of the function or the name of the data item determines the section's name in the output file. Use these options on systems where the linker can perform optimizations to improve locality of reference in the instruction space. Generally reduces the linked application size. Commonly used.

  • Other optimization flags: For new Optimization -f (flags) introduced, the user can add these flags in here to pass them to the compiler.

4. Warnings

  • Check Syntax only : Warning on syntax only
  • No Common: Allocate even uninitialized global variables in the data section of the object file, rather than generating them as common blocks. This has the effect that if the same variable is declared (without extern) in two different compilations, you will get an error when you link them.
  • Pedantic: Issue all the warnings demanded by strict ISO C; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C. This option follows the version of the ISO C standard specified by any '-std' option used.
  • Pedantic warnings as errors: Like '-pedantic', except that errors are produced rather than warnings.
  • Inhibit all warnings: Disable all warnings (not recommended)
  • All Warnings: Enable all warnings.
  • Extra warnings: Reserved for future version.
  • Warnings as errors: Treat all warnings as error.

Hint: If you want to use a specific warning flag(s), you must unclick the "All Warnings" flag

5. Miscellaneous

  • Language Standard : Commonly used the C90 with GNU extension or the C99 with the GNU extension
  • Assembler listing: specify the file name of the .lst file generated for each source file
  • Do not inline functions: Forbid the compiler from inlining function and generate calls to every function even if it is repeated.
  • Char is signed : treat char type always as signed char (not recommended slower code will be generated)
  • Bitfields are unsigned: Treat bitfields as unsigned.
  • Verbose: Print (on standard error output) the commands executed to run the stages of compilation. Also print the version number of the compiler driver program and of the preprocessor and the compiler proper.

Thunder ARM C/C++ Linker Options:

1. Sumamry page (C/C++ linker option)

  • Summary Page: This page is for information only, it states the path of the active linker, and a collection of all options used and passed to the linker, and the command line pattern. Not commonly used or modified. Please use defaults.

2. General

  • Do not use standard start files : Do not use the standard system startup files when linking. The standard system libraries are used normally, unless -nostdlib or -nodefaultlibs is used
  • Do not use default libraries: Do not use the standard system libraries when linking. Only the libraries you specify will be passed to the linker. The standard startup files are used normally, unless -nostartfiles is used. The compiler may generate calls to memcmp, memset, memcpy and memmove. These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified.
  • No startup or default libs: Only search library directories explicitly specified on the command line. Library directories specified in linker scripts (including linker scripts specified on the command line) are ignored.
  • Remove unused sections: Discard unused sections, generally produced less code
  • Print removed section: output to standard console the section the linker has removed or unused for reference.
  • Omit all symbols information: Do not include symbol information for the debugger.
  • Do not use shared libraries: Use static libraries.
  • Script file: This is one of the most important option int h e ARM linker, the scrip file is where you declare your memory regions and Flash and RAM sections. Please check linker script file reference. Normally if you use a ThunderBench wizard to create or import a project, this is automatically set by the wizard.

3. Libraries

  • Use Nano libraries: this will instruct the linker to link smaller footprint C runtime library (a msaller verison of libc.a). In general this produces less code size, it will link smaller (limited in floating point support) printf() or sprintf()
  • Libraries: Link additional libraries, other than the standard libraries. Additional libraries could be user libraries or supportive libraries like libm.a  (the math library). You dont have to add "lib" or ".a" , by simply put in "m" the linker will understand to link libm.a .
  • Library search path: Add the Paths for linker to look for the libraries listed in Libraries option.

4. Miscellaneous

  • Linker flags: You can pass to the linker extra flags or new flags not listed in the current release
  • Map file name: To setup the file name of the .map file generated by the linker where you can find information about all functions and symbols allocation and sizes.
  • Cross reference: Generate a cross reference symbols for the debugger, cross reference every .C function with its corresponding assembly generated by the compiler.
  • Print link map : output the .map file to the console (not recommended)
  • Verbose: Print (on standard error output) the commands executed to run the stages of linkin. Also print the version number of the linker
  • Other flags: You can pass to the linker extra flags or new flags not listed in the current release

 

For assistance please contact support .

 

If your project does not use CMSIS or any of these handy intrinsic functions is not already declared somewhere in your project, you can declare and use these intrinsic functions like enable or disable interrupts. The user can also add his own intrinsic functions, with single or multiple assembly instructions.

/**********************************
* Intrinsic Functions Declarations if CMSIS not used
*/
__attribute__( ( always_inline ) ) static inline void __enable_irq() { __asm volatile ("cpsie i"); }
__attribute__( ( always_inline ) ) static inline void __disable_irq() { __asm volatile ("cpsid i"); }

__attribute__( ( always_inline ) ) static inline void __enable_fault_irq() { __asm volatile ("cpsie f"); }
__attribute__( ( always_inline ) ) static inline void __disable_fault_irq() { __asm volatile ("cpsid f"); }

__attribute__( ( always_inline ) ) static inline void __WFI() { __asm volatile ("wfi"); }
__attribute__( ( always_inline ) ) static inline void __WFE() { __asm volatile ("wfe"); }
__attribute__( ( always_inline ) ) static inline void __SEV() { __asm volatile ("sev"); }
__attribute__( ( always_inline ) ) static inline void __ISB() { __asm volatile ("isb"); }
__attribute__( ( always_inline ) ) static inline void __DSB() { __asm volatile ("dsb"); }
__attribute__( ( always_inline ) ) static inline void __DMB() { __asm volatile ("dmb"); }
__attribute__( ( always_inline ) ) static inline void __CLREX() { __asm volatile ("clrex"); }

Example:
To disable interrupts:  call   __disable_irq(); in your code.  
 

For assistance please contact support .

 

Software tracing enables the user to trace into the assembly instructions to get a sense of the flow of the application while it is running. It helps detecting runtime errors and other situations when the application gets stuck at a certain point and the user needs to know why and where. ThunderBench supports software tracing and its controls are found in the disassembly view in the debugger. The main differences between software user controlled tracing and the expensive hardware solution is :

Software Hardware
Does not need expensive hardware JTAG/SWD Probes, or any modifications to your target boards. If you can debug it you can trace it ! The user needs to condition his target board to accommodate a tracing port, and get expensive hardware JTAG probe to enable tracing.
Tracing solution is readily available the first day the user download and debug his application. The user must determine if their target supports tracing, get the proper hardware, test it if it works or not, bare more expenses to enable tracing  etc...
Works on all targets whether they support ETM or not, with no special setup. Must properly initialize the ETM register, must be a target with ETM support.
Slower tracing but not limited Faster but limited to the tracing probe buffer.
Helps detecting the status of MCU before a triggered hard-fault, divide by zero etc.. Helps detecting the status of MCU before a triggered hard-fault, divide by zero etc..
The user can enable tracing information plus all registers value. Not Available.
The user can enable/disable tracing into certain functions, like avoiding library calls. Limited choice
Does not skip any instruction. Skips instructions, just gives the user the general flow of the application.
Software BKPT instruction supported Not widely supported.

 

One major use of tracing is to determine the status of the MCU just before the Hard-Fault to determine what causes the Hard-Fault. Both software and hardware Tracing provide this capability, and here is an example how to simulate and how to determine the cause(s) of the Hard-Fault.

Let's simulate a hard-fault:

  1. Put an illegal instruction somewhere in your main() function, preferably after MCU system and clock initialization. The instruction can be simply:
    __asm("BL 0xAAAAAA");   /* this is an illegal instruction and will certainly trigger a hard-fault*/ .
  2. In your hard-fault handler interrupt insert a breakpoint; example :
    void HardFault_Handler(void)
    {
      /* Complete Break and halt MCU when a Hard-Fault is triggered */
      __asm("BKPT");
    }
    this will enable the user to examine the trace immediately after a Hard-Fault is triggered.
  3. Start the debugger and break at the closest point where a Hard-Fault is suspected. In our example break on a function call or two before the offending __asm("BL 0xAAAAAA"); source line.
  4. Enable recording in the the disassembly view window by clicking on the Red enable/disable recording.
  5. Click on the Blue icon to start the actual tracing.
  6. You can see the Auto-Step feature running in front of your eyes, averaging 4-5 instructions per second, and your code will execute live in the debugger.
  7. Once the code reaches the offending instruction listed above, you notice the application triggers the Hard-Fault interrupt.
  8. What happens next? The application and the auto tracing stops, acknowledges the BKPT instruction is reached, and the debugger opens the trace log file.
  9. Examine the trace log file and scroll to the end of it, you can clearly see the Hard-Fault BKPT, and what is of interest to us are the few instructions preceeding to the Hard-Fault, to detemine what led to the Hard-Fault.
  10. In our example, the user can see clearly, that right before the Hard-Fault, the __asm("BL 0xAAAAAA"); was executed.

Interpretation:
When the Hard-Fault simulation above is triggered, the user must read carefully the address where the the application was, right before the Hard-Fault, and jump to that address using the disassembly view or memory view to determine the function or the source line where the offending instruction was executed. Future versions will be able to allow the user to jump directly to the source of the offending line that triggered the Hard-Fault.

Software Tracing will also help the user determine the offending source line where you have a divide by zero situations, where the compiler generates an ARM instructions in a Thunmb mode, and other situations.

To use SoftTrace without any situation, or just for tracing information, you can start and stop the auto tracing into your application, and check the trace log. You can also manually step-into or step-over into your application while capturing trace information. The settings button will enable/disable tracing options, like whether to capture all MCU registers with every step or not.

For assistance please contact support .