Debugging ARM Cortex-M0+ Hard Fault with MTB Trace

And here it is again: a Hard Fault exception raised by the ARM Cortex-M0+ on my Freedom board:

Hard Fault in Debug View

Hard Fault in Debug View

A reason for hard faults are for example dereferencing a NULL pointer. The issue with the ARM Cortex hard fault exception stack is: it is not easy to find out where in the code the problem is.I have created a Processor Expert component to help me to find the location of such an exception. With the Eclipse based CodeWarrior for MCU10.3 there is another way: Trace with the MTB (Micro Trace Buffer)!

💡 The Trace functionality was not part of the MCU10.3 beta, but is present in the final 10.3 release.

Micro Trace Buffer

The name MTB (Micro Trace Buffer) already indicates what is behind this tracing method: ARM has added support in the silicon which logs trace information in a memory buffer in RAM. If configured properly, a tool (like CodeWarrior debugger) will read that buffer in RAM and processes the information. The good thing with MTB is: the location in RAM and the size is user configurable: it is simply a buffer somewhere in the RAM. Using MTB Trace does not need any special hardware: a normal debug connection like OpenSDA is good enough. Of course anything faster than OpenSDA helps speeding up things, so using a higher performance run control device makes a lot of sense (not only for Trace).

Enabling Trace

While the Processor Expert HardFault component needs Processor Expert, using Trace works of course for any project.

💡 If you are migrating a MCU10.3 beta project to MCU10.3 final for Trace, you need to do the steps outlined in Migrating Kinetis-L Projects.

Trace is configured in the ‘Trace and Profile’ tab inside the Debug/Launch configuration. It is enabled with the ‘Enable Trace and Profile’ check box:

Enabling Trace

Enabling Trace

This will a reminder dialog that I need to rebuild my project:

Trace Enabled

What happens with enabling trace

Wondering what is behind enabling that trace option, and why I need to rebuild my project?

Rebuild is necessary because it has added/changed a define in my preprocessor settings:

Defined Symbol for Trace

Defined Symbol for Trace

This symbol is used in the sa_mbt.c file within my project:

SA_MTB_SIZE in sa_mtb.c

SA_MTB_SIZE in sa_mtb.c

This mtb_buf is added to the m_data section in my linker file:

mtb_buf in linker file

mtb_buf in linker file

I do not need to do anything for the things above: it is configured automatically by CodeWarrior.

Tracing with Debug

After rebuilding my application, I start debugging as usual. The difference is that there are two more buttons in my Debug view:

Trace Buttons in Debug View

Trace Buttons in Debug View

The first button is to start/stop trace collection, and the other is to reset the trace data.

Additionally there is an extra view: the Software Analysis view:

software analysis view

software analysis view

💡 The view is added with the menu Window > Show View > Other > Software Analysis

After I have run into my Hard_Fault Exception, I click on the ‘Trace’ link:

Opening Trace

Opening Trace

This opens the a view showing the trace collected:

Trace Data

Trace Data

To see what happened last, I need to go to the end of the list:

End of Trace

End of Trace

The MTB trace does not record every instruction: it records ‘change of flow’ to reduce the memory needed.

Linked with Source

While the ‘raw’ trace data already gives an idea what happened in my application, there is a nice feature which might not be obvious the first time: I can click into the trace data or use the buttons in the trace view to go to the next or previous trace item in the list. The cool thing is that it links to the source file and puts a marker there:

Source following trace

Source following trace

💡 To go back and forward in trace and have it follow in the source, it is best to have the two views side by side arranged as in my above screen shot.

Ok, now I clearly see what has caused my exception: the pointer ‘p’ in my code has not been initialized properly. Finding the issue was not that easy, but the fix for it is :-).

Happy Tracing 🙂

39 thoughts on “Debugging ARM Cortex-M0+ Hard Fault with MTB Trace

  1. Pingback: Version Control with Processor Expert Projects | MCU on Eclipse

  2. Pingback: First Steps with the P&E Tracelink | MCU on Eclipse

  3. Hello Erich.

    I opened the Debug Configurations window and the “Trace and Profile” tab is there, but the “Enable Trace and Profile” is not enabled. I cannot click on it to enable it.

    Do you know why this is?

    I am using CodeWarrior for MCU, Version: 10.3, Build Id:120924.

    I appreciate any help. Thank you.

    Like

    • Hi Luis,
      from the build ID you are using the MCU10.3 beta. That version does not support MTB Trace. You need MCUC10.3 for this. You can install that MCU10.3, whild still having your beta installed (just in case). Just install the 10.3 into a different folder. That might be useful as the final 10.3 has a code size limitation of 64 KByte for Kinetis, while the 10.3beta is unlimited.

      Like

      • Hello Erich.

        Thanks for that. I installed the new version and enabled the trace option. I first did the steps for migrating a beta project.

        But now when I start debugging I get an error that says:

        MTB Buffer Attributes error

        Reason:
        Could not read the MTB buffer allocation data in elf.
        Trace disabled.

        Any idea why that is?

        Thanks.

        Like

      • Hello Erich,

        Yes I did. I set memory areas to the default, I created the sa_mtb.c file with the code you provided, I generated the code and built the project.

        Is it necessary to do an #include of the sa_mtb.c file in some part of the ProcessorExpert.c file?

        I will try that. Thanks.

        Like

        • Hi Luis,
          no, there is no additional include needed. Maybe I missed someting in my description? Could you try with a newly created project (as this will set up things properly)?
          For sure you need to enable trace in the debugger settings, and then you need to rebuild the project.
          One thing I noticed: do not change the trace settings trough the Project > Properties context menu: do it through the menu Project > Run > Debug Configurations.

          Like

      • Hello Erich.

        I did a brand new project, copied the components and the code to make it exactly as the original one.

        Everything worked that way. I don’t even get the hard fault anymore, so I didn’t need the micro trace buffer. I enabled it anyway just to check if it was working, and it was. I didn’t get the MTB Buffer Attributes error.

        I guess there’s no way of knowing what caused that problem as I had some problems with the project previously and did some renaming. That may have caused the problem. Besides that, maybe I missed something in the importing to CW10.3 process.

        Anyway, I really appreciate your help.

        Thanks.

        Like

  4. Hello Erich, can you guide me on how to enable trace in IAR? I am using the same Freedom board.

    Thank you.

    Like

    • Hi See,
      the Trace window usually opens in the area where the sources are (as a tab). Simply drag&drop the trace window side-by-side the source window, so you can see both, as seen in the sreenshot of this post.
      Let me know if you need further details.
      I hope this helps,
      Erich

      Like

    • I would disagree to label this as a bug for the debugger. I think it can be labeled as ‘missing feature’. But I think the debugger would need to be very intelligent about it. All the solutions I see so far are either the same as the one I’m proposing (installing a special handler), or that the debugger has an option if you are in the hard fault to show the registers (the debugger is doing the same as the handler). Thanks for the link to that article: but yet again in this article it is proposing the same approach as here: to write a handler (by the user for the application) which then gets the hard fault details. Are you making the point that the Keil debugger is implementing the feature you suggest? What I see in the article you refer to is not the debugger doing this, but the user application on the board.

      Like

  5. I am just wondering, is there a plugin anywhere for eclipse that could allow you to do Trace and Profile in eclipse without CodeWarior? just asking… 🙂

    Like

  6. Hi Eric,

    I am trying to get trace working in CodeWarrior on a custom Makefile project. Do you have any idea what symbols are necessary in the .elf file for CodeWarrior to locate the MTB buffer? I have declared a buffer with the name mtb_buf exactly as on line 13 of sa_mtb.c in your example code above, have added a section called .mtb in my linker script using exactly the same text as in your linker script example, and then tried to enable tracing.

    I have verified the symbol mtb_buf, _mtb_start, and _mtb_end are all defined in the .elf file and have the correct values (as determined by the map file generated by the -Map linker flag), but I still get a dialog box with the error message:

    MTB Buffer Attributes error

    Invalid MTB buffer allocation data in elf.
    Make sure MTB support has been added to project and the project has been rebuilt.

    Can you tell me exactly what symbols CodeWarrior is looking for in order to enable tracing, and how do I enable those manually?

    Thank you for any advice. I am trying to track down a HardFault condition which is proving particularly elusive.

    Like

    • Hi Chris,
      You need a symbol mtb_buf in your application (see sa_mtb.c) in the example projects. That buffer needs to be aligned on a 64 byte boundary. Make sure that it does not get stripped off by the linker:
      /* reserve MTB memory at the beginning of m_data */
      .mtb : /* MTB buffer address as defined by the hardware */
      {
      . = ALIGN(8);
      _mtb_start = .;
      KEEP(*(.mtb_buf)) /* need to KEEP Micro Trace Buffer as not referenced by application */
      . = ALIGN(8);
      _mtb_end = .;
      } > m_data

      Like

  7. Hi Erich,

    I’d like to contribute a work around for a trace bug we have seen at the office:

    The bug:

    We have been using a modified version of your bootloader example (replaced the UART for USB) to load our hex/S19 firmware files unto our custom boards. However, the bootloader started complaining about the firmware files since we started using the MTB. So I opened up the “Trace and Pofile” tab on the “Debug Configurations” window and I noticed that we had already disabled the “Enable Trace and Profile” option. However, opening the project’s properties window revealed that the compiler’s “__SA_MTB_SIZE” preprocessor directive was still defined.

    The solution:

    I removed the preprocessor directive using the project’s properties window.

    The bug’s effects on the hex/S19 files:

    Additional address and instruction lines appear at the end of the hex file. These lines start with the “S3” directive. The bootloader stops downloading firmware and complains about these lines. Often the bootloader becomes unresponsive after complaining about these lines and the bootloader showing an “ERROR! Failed at address…” message. Once the bootloader becomes unresponsive it’s necessary to hard reset the MCU to bring the board to a responsive state.

    As always, thanks for your tutorials! I hope this post will be of help.

    Like

  8. Hi Erich,
    I use CW10.6, Kinetis k chips.
    And I want to use the software trace or tracepoints function , i refer to the “Profiling and Analysis Users Guide.pdf” under CW10.6 can did it . while i’m unable to read the “trace data view ” , i don’t know the meaning of each portion . Could you recommend me something demo or reference manual about this to me .

    Thank you very much !

    Like

  9. Hi Erich

    do we have this MTB on Kinetis design Studio
    and how to enable on KDS, i dont see trace tab in Debugger setting.
    ii am using KDS.3.0

    Like

  10. Pingback: Tutorial: Catching Rogue Memory Accesses with ARM Watchpoint Comparators and Instruction Trace | MCU on Eclipse

  11. Hi Erich,
    I wanted to know if you have tried to integrate Eclipse with Jlink debugger for Cortex-m0+ MTB trace functionality. If so, can you please point me to the tutorial? I did try to run a search string on your landing page, but this tutorial is the one I was able to find and it doesn’t use Eclipse.
    Many thanks.
    Regards,
    Radhika

    Like

  12. Pingback: Tutorial: How to Optimize Code and RAM Size | MCU on Eclipse

What do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.