Startup Completion with Ozone

From SEGGER Wiki
Revision as of 09:39, 24 February 2020 by Jonas (talk | contribs) (Overview)
Jump to: navigation, search

Overview

This wiki article explains Ozone's startup completion behavior, the project settings affiliate with startup completion and how the debugger initializes itself for RAM-debug.

Startup Completion Point

The system variable editor can be accessed from the tools menu.

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 Edit.SysVar.

Input format Example
Instruction address 0x8000700
Function name main
Assembly label __startup_complete

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 CM_ATTACH or CM_ATTACH_HALT.

Debugger Actions Taken On Startup Completion

When program execution reaches the startup completion point, Ozone:

Startup completion reoccurs each time the startup completion point is reached following program reset.

OnStartupComplete

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 using command Debug.ReadIntoInstCache.

Instruction Cache

All instruction-level debug features of Ozone, including:

  • Disassembly
  • 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 Debug.ReadIntoInstCache. Instruction-level debug information which is unavailable due to an incompletely initialized instruction cache is indicated by a warning sign.

When the instruction cache misses data for a particular code address range, Ozone will display a warning symbol next to all affected GUI elements.

Note that each time the instruction cache is updated, Ozone also calls J-Link API function Debug.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

Ozone command 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 function 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

  • trace
  • 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

RAM Debug

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 from 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

Media:ES_CortexM_RAMFunc.zip

This project executes functions from both Flash and RAM. The startup code and functions main() and 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

References

  • Ozone User Guide, Sections Startup Completion Point and Setting Up The Instruction Cache.
  • J-Link User Guide, Section Debug.ReadIntoTraceCache
  • System V Application Binary Interface (ELF), Edition 4.1