Startup Completion with Ozone
- 1 Overview
- 2 Startup Completion Point
- 3 Instruction Cache
- 4 Target Data Acquisition
- 5 RAM Debug
- 6 References
This wiki article explains Ozone's startup completion behavior and the project settings affiliated with startup completion. Among the benefits, handling of the startup completion event enables Ozone to support RAM debug out-of-the box, without the need for any user configuration.
Startup Completion Point
Ozone system variable
VAR_STARTUP_COMPLETION_POINT identifies the program execution point where the debuggee has completed memory initialization. This PC is implementation-defined and not necessarily
identical to the program’s entry point function.
VAR_STARTUP_COMPLETION_POINT is a string-type system variable which accepts the inputs shown in the table below. The default value of the variable is the program's entry point (main) function.
The variable can be edited via Ozone's system variable editor or from the project script using command
Knowledge about the startup completion point enables Ozone to safely initialize its instruction-level debug information once the entire machine code of the debuggee is accessible to the debugger. For example, a debuggee may decompress parts of the program code into target RAM before branching to the main function. In this situation, the compressed machine code is not accessible to the debugger before startup completion.
Empty Startup Completion Point
When the startup completion point is set to an empty string, startup completion is defined to occur on the first CPU halt.
Startup Completion Point When Attaching
When the program is not reset during target connection, startup completion is defined to
occur on the first CPU halt. This is the case when the connection mode is
Debugger Actions Taken On Startup Completion
When program execution reaches the startup completion point, Ozone:
- updates its instruction cache.
- calls project script function
- starts debug features that access target memory, such as RTT and data sampling.
Startup completion reoccurs each time the startup completion point is reached following program reset.
Ozone calls project script function
OnStartupComplete each time the startup completion point has been been reached or passed.
It is thus ensured that target memory is initialized and readable when this script function is called.
This script function is the preferred place place to perform manual initializations of the instruction cache
All instruction-level debug features of Ozone, including:
- Instruction trace
- Code profile
- Call graphs
- Function instruction counts
require the debugger to perform an initial analysis of the machine code to be debugged. For performance reasons, Ozone stores the results of any instruction analysis it performs into its instruction cache. The instruction cache is updated upon entry of the following debug events:
|Debug event||Instruction cache updated with|
|Program file open||Machine code segments that can be read from the program file|
|Startup Completion||Machine code segments that cannot be read from the program file but from target memory|
|Disassembly Plugin Loaded||All program code areas|
|Target configuration changed||All program code areas|
This means that when:
- the debuggee’s machine code is fully accessible from the program file or
- the debuggee’s machine code is fully accessible from target memory at the Startup Completion Point,
the debugger will perform the instruction analysis automatically and no user interaction or project configuration is required. In all other cases, e.g. when:
- a non-ELF program file is specified,
- a secondary program image is in use, such as a bootloader,
parts of the instruction cache may need to be initialized manually.
For this purpose, Ozone provides the command
Instruction-level debug information which is unavailable due to an incompletely initialized
instruction cache is indicated by a warning sign.
Note that each time the instruction cache is updated, Ozone also calls J-Link API function
ReadIntoTraceCache to update the trace cache of the J-Link firmware. Thus, explicitly initializing the trace cache from the project script is not required.
Debug.ReadIntoInstCache(Addr,Size) can be called from the project script in order to
update Ozone's instruction cache within an arbitrary memory address range.
The command has two arguments which are the address and size of the memory address range to analyze.
The preferred way to employ this command is to call it from project script
OnStartupComplete, when target memory is ensured to be initialized and readable.
This command returns 0 on success and -1 on error.
Target Data Acquisition
Debug features that use or acquire
- target memory data
are started at the startup completion point, as summarized below.
|Attach||Attach & Halt||Download & Reset|
|Semihosting||Target connect||On halt||Startup complete|
|RTT||Target connect||On halt||Startup complete|
|SWO||On first halt||On halt||Startup complete and after reset|
|Trace||On first halt||On halt||Startup complete and after reset|
|Init Inst. Cache||On first halt||On halt||Startup complete|
|Data/power sampling||Target connect||On halt||Startup complete|
Standard toolchains, such as GCC, store a copy of the ELF file's RAM segment, i.e. the initialization image, as Flash segment to the ELF file. At program execution time, startup code then simply copies the initialization image to the destination RAM area. With advanced linkers, such as the SEGGER Linker, the initialization image can also be compressed, which saves some Flash memory. In rare cases, the ELF program may even contain no initialization image at all but rather construct RAM-code via an algorithm.
RAM Debug of Functions copied From Flash
Ozone handles ELF files with copied initialization image the same way as ELF files with pure flash content;
all instruction-level debug information is readily available when the ELF file is opened.
The setting of system variable
VAR_STARTUP_COMPLETION_POINT is irrelevant regarding RAM-debug in this case.
RAM Debug of Functions not copied From Flash
When debugging ELF programs with decompressed or algorithmically initialized RAM code, the setting of system variable
VAR_STARTUP_COMPLETION_POINT is relevant and may have to be adjusted.
The system variable tells Ozone when it can safely read machine code from target memory in order
to provide instruction-level debug information for the decompressed code areas.
RAM Debug of non-ELF Functions
In cases when:
- a non-ELF program file is specified,
- a secondary program image is loaded to target memory,
- the target executes from code areas not covered by the program file,
Ozone is usually unable to automatically initialize its instruction cache with these additional code areas.
Accordingly, users must setup the project script to update Ozone's instruction cache as required.
For this, command
Debug.ReadIntoInstCache is provided.
RAM Debug Example Project
This project executes functions from both Flash and RAM.
The startup code and functions
MAIN_FlashFunc() execute from Flash,
all other functions, including ISRs, execute from RAM.
The startup code finishes RAM initialization before
main() is reached.
To debug and trace this example, no special configuration is required.
Ozone will automatically identify the program's code segment types and initialize its instruction cache accordingly.
Since the example contains compressed RAM code, the instruction cache will be initialized partially at program load time and partially upon startup completion.
The project is configured to run on the emPower Board, but the application can run on any Cortex-M4 device with Flash at 0x00000000 and RAM at 0x2000000000.
The application outputs a simple message:
Executing main() from Flash @ 0x00000410. Executing APP_Main() from Flash @ 0x200009B8. Tick Count: 1500 Tick Count squared: 2250000 Tick Count: 2000 Tick Count squared: 4000000
- Ozone User Guide, Sections Startup Completion Point and Setting Up The Instruction Cache.
- J-Link User Guide, Section ReadIntoTraceCache
- System V Application Binary Interface (ELF), Edition 4.1