Difference between revisions of "Using Snapshots with Ozone"

From SEGGER Wiki
Jump to: navigation, search
m
m (Debugger Commands)
Line 166: Line 166:
   
 
The following debugger commands can be employed within project script functions ''OnSnapshotLoad'' and ''OnSnapshotSave''
 
The following debugger commands can be employed within project script functions ''OnSnapshotLoad'' and ''OnSnapshotSave''
to access snapshot file data. All of the below commands are documented in the appendix of the Ozone user guide, section User Actions.
+
to access and apply snapshot file data. All of the below commands are documented in the appendix of the Ozone user guide, section User Actions.
 
When a register group was stored to the snapshot, each group register can be
 
When a register group was stored to the snapshot, each group register can be
 
read from the snapshot individually. All register data is written to the target on a per-register basis.
 
read from the snapshot individually. All register data is written to the target on a per-register basis.

Revision as of 14:32, 1 July 2019


Overview

Ozone Debug Snapshots (snapshots for short) are a new feature of Ozone, introduced in version 2.63. Snapshots allow saving of the entire system state.

This includes:

  • RAM
  • Flash
  • CPU registers
  • Selected Peripherals
  • Timeline
  • Code Profile (Execution Counters)
  • Data Graphs
  • Power Graphs
  • Terminal Log
  • Console Log

After loading a snapshot, all debug windows show the same information they did (or would have, had they been visible) at the time the snapshot has been created. This includes the call stack, symbol, task, memory and register windows.

Advanced target state, such as clock, IRQ and peripheral configurations, can be precisely restored from a snapshot. This means that even complex multi-tasking programs and programs with peripheral IO can be resumed from the snapshot point.

Snapshots can be loaded and observed in target-offline mode. This means that no hardware is required to load a snapshot, not even a J-Link or J-Trace.

Use Cases

Typical use cases of snapshots are:

  • Snapshots allow customers to break away from a debug session with the ability to resume the session at a later point in time.
  • Snapshots allow easier reproduction and analysis of bugs, possibly by multiple parties on different Host-PCs.
  • Snapshots enhance Ozone's teaching and demonstration capabilities in training sessions and conferences.
  • Snapshots as an archiving media.

Saving Snapshots

The snapshot dialog allows users to define what data will be saved to the snapshot. In particular, the dialog provides two sub-dialogs that allow to define what components of the system state, i.e. which memory regions, CPU, floating-point and peripheral registers, are to be saved. The dialog can be accessed from the debug menu or by executing command "Debug.SaveSnapshot"

SnapshotSave.png

The default configuration of the register selection dialog, and thus the default set of target registers stored to snapshots, are:

  • all basic CPU registers, including FP registers.

The default configuration of the memory selection dialog, and thus the default set of target memory regions stored to snapshots, are:

  • all FLASH and RAM region defined for the target within the MCU database of the J-Link API.
  • all ELF program data sections with the allocatable flag (A) set.

These default configurations can be restored by clicking on button "Restore Defaults". Button "Import" allows to add memory regions from a SEGGER Embedded Studio memory map file. Button "Save" makes the current configuration persistent by storing it to the user file of the project (jdebug.user).

Snapshots are file-stream-compressed using SEGGER's emCompress software library. The disk format is documented at: trunk/Doc/Ozone/Ozone_Snapshot_Disk_Format.txt

Loading Snapshots

The load snapshot dialog can be accessed from the debug menu or by executing command "Debug.LoadSnapshot".

SnapshotLoad.png

When a snapshot is loaded, registers and memory regions are restored in the order they appear within the snapshot. This order is identical to the order displayed by the memory- and register selection dialogs. There is a peculiarity when loading snapshots in target-online mode: any non-basic CPU register is not immediately written to the target. Instead, the user must program the specific way in which system, peripheral and memory-mapped registers are to be applied to target, as explained below.

Scripting Snapshot Load/Store

In order to restore advanced system state, such as (clocked) peripherals from a snapshot, it is generally necessary for users to program the exact sequence of restore operations. To support this, Ozone provides the script functions OnSnapshotSave and OnSnapshotLoad and a command group Snapshot tailored to reading and writing to/from snapshot files.

The following script example restores the system state of an embOS blinky debuggee on a SEGGER Cortex-M trace reference board when the snapshot is loaded:

void OnSnapshotSave (void) {   
  //
  // Save vector table offset register
  //
  Snapshot.SaveReg("CPU.Peripherals.SCB.VTOR");
  //
  // Save system timer configuration
  //
  Snapshot.SaveReg("CPU.Peripherals.SYSTICK");
  //
  // Save Cortex-M IRQ priorties 12-15 (SYSTICK)
  //
  Snapshot.SaveReg("CPU.Peripherals.SCB.SHPR3");
  //
  // Save clock configuration
  //
  Snapshot.SaveReg("Peripherals.RCC.CR");
  Snapshot.SaveReg("Peripherals.RCC.CFGR");
  Snapshot.SaveReg("Peripherals.RCC.PLLCFGR");
  //
  // Save GPIOA clock configuration
  //
  Snapshot.SaveReg("Peripherals.RCC.AHB1RSTR");
  Snapshot.SaveReg("Peripherals.RCC.AHB1ENR");
  //
  // Save GPIOA port state
  //
  Snapshot.SaveReg("Peripherals.GPIO.GPIOA.MODER");
  Snapshot.SaveReg("Peripherals.GPIO.GPIOA.ODR");
}
                                                              
void OnSnapshotLoad (void) {   
  //
  // Restore vector table offset register
  //
  Snapshot.LoadReg("CPU.Peripherals.SCB.VTOR");
  //
  // Restore system timer configuration
  //
  Snapshot.LoadReg("CPU.Peripherals.SYSTICK");
  //
  // Restore Cortex-M IRQ priorties 12-15 (SYSTICK)
  //
  Snapshot.LoadReg("CPU.Peripherals.SCB.SHPR3");
  //
  // Restore clock configuration
  //
  Snapshot.LoadReg("Peripherals.RCC.CR");
  Snapshot.LoadReg("Peripherals.RCC.CFGR");
  Snapshot.LoadReg("Peripherals.RCC.PLLCFGR");
  //
  // Restore GPIOA clock configuration
  //
  Target.SetReg("Peripherals.RCC.AHB1ENR", 0);
  Snapshot.LoadReg("Peripherals.RCC.AHB1RSTR");
  Snapshot.LoadReg("Peripherals.RCC.AHB1ENR");
  //
  // Restore GPIOA port state
  //
  Snapshot.LoadReg("Peripherals.GPIO.GPIOA.MODER");
  Snapshot.LoadReg("Peripherals.GPIO.GPIOA.ODR");                                   
}

As can be seen, any register can specified using its qualified SVD tree path name. The snapshot scripting facility is currently targeting the target system register state only. All other target data is automatically written to target when a snapshot is loaded in target-online mode, irrespective of the presence of above script functions.

Debugger Commands

The following debugger commands can be employed within project script functions OnSnapshotLoad and OnSnapshotSave to access and apply snapshot file data. All of the below commands are documented in the appendix of the Ozone user guide, section User Actions. When a register group was stored to the snapshot, each group register can be read from the snapshot individually. All register data is written to the target on a per-register basis.

Command Description
Snapshot.SaveReg(const char* sReg) Saves a register (group) to a snapshot
Snapshot.SaveU32(U64 Addr, U32 Value) Saves a memory value to a snapshot
Snapshot.ReadReg(const char* sReg) Reads a register from a snapshot
Snapshot.ReadU32(U64 Addr) Reads a memory value from a snapshot
Snapshot.LoadReg(const char* sReg) Reads a register (group) from a snapshot and writes it to target
Snapshot.LoadU32(U64 Addr) Reads a memory value from a snapshot and writes it to target
Register.Addr(const char* sReg) Gets the memory address of a memory-mapped register
Target.WriteU32(U64 Addr, U32 Value) Writes a 32 bit value to target memory
Target.ReadU32(U64 Addr) Reads a 32 bit value from target memory
Target.SetReg(const char* sReg, U64 Value) Writes a CPU or system register
Target.GetReg(const char* sReg) Reads a CPU or system register