Ozone — Trace Features
Ozone is more than a simple debugger, it is a performance analyzer that offers trace features for deep-insight system analysis.
- Stand-alone graphical debugger
- Debug output of any tool chain and IDE 1
- C/C++ source level debugging and assembly instruction debugging
- Debug information windows for any purpose: disassembly, memory, globals and locals, (live) watches, CPU and peripheral registers
- Source editor to fix bugs immediately
- High-speed programming of the application into the target
- Direct use of J-Link built-in features (Unlimited Flash Breakpoints, Flash Download, Real Time Terminal, Instruction Trace)
- Scriptable project files to set up everything automatically
- New project wizard to ease the basic configuration of new projects
1 Ozone has been tested with the output of the following compilers: GCC, Clang, ARM, IAR. Output of other compilers may be supported but is not guaranteed to be.
With direct integration of J-Trace, Ozone enables CPU trace and offers different possibilities to analyze the run-time behavior and performance of your target system. CPU trace enables you to get full system insight, far more than what is possible with simple debugging and printf-style output.
Ozone's trace-related windows provide multiple ways and views to find bugs and inefficiencies and to verify that a system behaves as expected.
Tracing does not have to require any target code modification or huge setup. Get up and running in less than 15 minutes with Ozone and J-Trace PRO.
The basic information provided by trace data is the instruction trace. When the target is halted, Ozone shows the most recently executed instruction in its Instruction Trace Window. This allows you to analyze what your system did last.
The Instruction Trace Window displays the program’s instruction execution history as a stack of machine instructions. The instruction at the bottom of the stack has been executed most recently. The instruction at the top of the stack was executed least recently. The instruction stack is partitioned into call frame blocks. Each call frame block contains the set of instructions that were executed between entry to and exit from a program function. Call frame blocks can be collapsed or expanded to hide or reveal the affiliated instructions. The number of instructions executed within a particular call frame block is displayed on the right side of the block’s header.
Both code windows, Source Viewer and Disassembly Window, highlight the instruction that is selected within the Instruction Trace Window. This allows you to replay system execution not only on instruction level, but on source level, too.
The Timeline Window provides a graphical representation of the Call Stack over time. The timeline is based on the recorded trace data, mapped to the source function information.
Each call frame of the timeline stack resembles a function invocation. With the timeline you can easily measure how long a function call took, which sub-routines have been called, and how much time has been spent in sub-routines. Discontinuities in program flow, for instance interrupts and context switches, are highlighted with a background color change to enable you to easily identify these highly significant events.
With OS awareness, the Timeline Window supports identification of task switches to restart the call stack. You can now see when task switches happen and which function calls belong to a task execution. Without OS awareness, the functions might endlessly stack when Ozone does not know where task switches happen.
The Timeline Window is synchronized with the Instruction Trace Window to allow fast navigation in your application flow and immediate identification of what you are currently looking at.
With the J-Trace PRO streaming trace capabilities, trace data is analyzed in real-time, while the data is transferred from the target system to the host computer. The analyzed data contains information about which instructions have been executed on the target, whether conditional instructions have taken both paths, and how often each instruction has been executed. With the captured trace data, Ozone analyzes your application to construct a code profile and identify "hot spots" for potential optimization.
What is Code Profiling?
Code profiling is a form of measuring the execution time and the execution count of functions, blocks or instructions. It can be used as a metric for the complexity of a system and can highlight where computing time is spent. This provides a great insight into the running system and is essential when identifying code that is executed frequently, potentially placing a high load onto a system. The code profiling information can help to easier optimize a system, as it accurately shows which blocks take the most time and are worth optimizing.
With streaming trace it is possible to get the most accurate code profiling information. It can be done without any source modification and is even possible on production code.
Ozone maps the execution counts to the high-level source code and show the number of execution for each function, block, or source line. The code profiling data can be updated in real time, while the target system is running. This allows identifying time-consuming or frequently called routines which may help to selectively optimize the system.
The trace capability can provide completely accurate information about the instruction execution on the target system. This enables a full code coverage analysis of the system which can be updated while the target is running.
What is Code Coverage?
Code coverage metrics are a way to describe the "quality" of code, as "code that is not tested does not work". A code coverage analyzer measures the execution of code and shows how much of a source line, block, function or file has been executed. With this information it is possible to detect code which has not been covered by tests or may even be unreachable. This enables a fast and efficient way to improve the code or to create a suitable test suite for uncovered blocks.In systems which interface with peripherals, such as USB, IP stacks or other components these tests should be run on actual hardware. Simulation environments on a computer cannot replicate timing, or other characteristics, of real hardware that might affect program execution. In addition, as with code profiling, code coverage analysis can be intrusive, by instrumenting code, or non-intrusive, by tracing the program counter. Code instrumentation might not work well with hard-real-time requirements of code and can therefore not be used to analyze advanced embedded systems. With a J-Trace PRO code coverage analysis is completely non-intrusive. It does not modify the code or alter the execution. With the streaming trace capability a whole test suite can be run in one go without requiring to halt or reload the test application.
Code coverage analysis is usually done with a test application, which triggers different routines of the actual code. And the routines run as they would do in the final system based on the given parameters. While the test runs, the generated instruction trace data is analyzed.
Ozone, gets the analyzed information and shows exactly which instructions or lines of code have been executed by running the test. In Ozone this is done by highlighting executed lines in the source viewer.
The code coverage information does not only show which lines have been fully executed, i.e. all instructions of a line are executed, but it can also show where conditions have not yet been fully met, i.e. have not been true and false. The highlighting of source lines provides a quick overview on which code has been covered. Uncovered source lines or blocks might then require additional test parameters to be tested, or need to be improved, fixed, or rewritten.
Additionally it is possible to create full code profile reports for analyzed modules or applications. These records include information about how many lines and instructions of each function are covered. Code coverage reports are usually required to be stored for QA processes or certification.
The trace features can be used when the target system supports CPU trace. There are two trace methods:
A J-Trace is connected to the trace pins of the target device. All trace data generated by the Embedded Trace Macrocell (ETM) is sent on these pins and recorded by J-Trace. With a J-Trace PRO the trace data is immediately sent to the host PC, which enables unlimited recording of the target execution and provides full system insight. With an older J-Trace the trace data is stored in a 64 MB internal buffer and the latest trace data, usually about the last 2 seconds of execution, is read by the PC when the target is halted.
If the target device includes an Embedded Trace Buffer (ETB) or similar, trace can be done with a J-Link. The trace data is then written by the target into the internal trace buffer of usually about a few kilobytes and read by J-Link when the target is halted. With a trace buffer the last few thousand executed instructions can be available, which does not provide full insight, but can be useful to recall the execution flow before a fault or issue occurs.