J-Link ARMv8-AR

From SEGGER Wiki
Jump to: navigation, search

This article describes the debugging specifics for ARMv8-A/R based chips & cores.

CoreSight auto-detection

When connecting to a ARMv8-A/R based core, J-Link will automatically scan the CoreSight space of the device to auto-detect the location of the core in that system.
Scanning is done by the following algorithm:

  • Scan CoreSight DP address space until an APB-AP is found. Scanning is stopped as soon as an APB-AP is found
    • Scanning is stopped after finding the AP because in a multi-core system it is not unlikely to have other APs following but these may be not clocked by default. This can cause DAP accesses to hang until the device is power-cycled.
  • Scan APB-AP address space until an "ARMv8-A/R core" CoreSight component has been found. This describes the debug registers of the core.
  • The CoreSight component that comes immediately after the Core is expected to be an CTI and assumed to be the CTI that is connected to the core we just found. If the next component after the core is not an CTI, the scan and connect procedure is aborted.
    • Scanning is stopped after the CTI because in a multi-core system it is not unlikely to have other cores following in the ROM table but these may be not clocked by default. This can cause DAP accesses to hang until the device is power-cycled, when accessing their CID / PID registers for identification.

Scanning for a CTI after the core has been found is needed for ARMv8-A/R based cores because the CTI connected to the core is the only way to halt / resume the core.
While for ARMv7-A/R halt / resume was possible via the debug registers, this option does no longer exist for ARMv8-A/R.

If the ROM table / CoreSight space of a specific device does not allow auto-detection of the core via scanning or if another core than the 1st one should be accessed, a J-Link script file is needed.
Below an example script file is given.

int ConfigTargetSettings(void) {
  //
  // Specify AP map
  //
  JLINK_ExecCommand("CORESIGHT_AddAP BaseAddr = 0x7C002000 Index=0 Type=AHB-AP");  // Connects to a Cortex-M4 coprocessor in the system
  JLINK_ExecCommand("CORESIGHT_AddAP BaseAddr = 0x7C004000 Index=1 Type=AXI-AP");  // Connects to system memory. May be used for RTT / HSS
  JLINK_ExecCommand("CORESIGHT_AddAP BaseAddr = 0x7C006000 Index=2 Type=APB-AP");  // Connects to 4x Cortex-R52 cluster in the system
  //
  // Specify core debug registers base address.
  //
  JLINK_ExecCommand("CORESIGHT_SetIndexAPBAPToUse = 2");
  JLINK_ExecCommand("CORESIGHT_SetCoreBaseAddr = 0x7E810000");      // Location in AP address space where debug registers of core are located
  JLINK_ExecCommand("CORESIGHT_SetCSCTICoreBaseAddr = 0x7E820000"); // Location in AP address space where CTI that connects to the core is located
  return 0;
}

RTT support

For more information about RTT, please refer to the dedicated wiki article.
While for the ARM M-profile cores (e.g. Cortex-M4) there is always an AHB-AP present that has access to everything the core has access to,
having an AHB-AP or AXI-AP that allows system memory accesses bypassing the core (background memory access) is optional for ARMv8-A/R.
Even if an AHB-AP or AXI-AP is present, J-Link may stop the AP scan before it is discovered or does not know what memories the APs have access to.
Therefore, for ARMv8-A/R, the AP (if present) to be used for background memory accesses must be manually specified via a a J-Link script file:

int ConfigTargetSettings(void) {
  //
  // Specify AP map
  //
  JLINK_ExecCommand("CORESIGHT_AddAP BaseAddr = 0x7C002000 Index=0 Type=AHB-AP");  // Connects to a Cortex-M4 coprocessor in the system
  JLINK_ExecCommand("CORESIGHT_AddAP BaseAddr = 0x7C004000 Index=1 Type=AXI-AP");  // Connects to system memory. May be used for RTT / HSS
  JLINK_ExecCommand("CORESIGHT_AddAP BaseAddr = 0x7C006000 Index=2 Type=APB-AP");  // Connects to 4x Cortex-R52 cluster in the system
  //
  // Specify core debug registers base address.
  //
  JLINK_ExecCommand("CORESIGHT_SetIndexAPBAPToUse = 2");
  JLINK_ExecCommand("CORESIGHT_SetCoreBaseAddr = 0x7E810000");      // Location in AP address space where debug registers of core are located
  JLINK_ExecCommand("CORESIGHT_SetCSCTICoreBaseAddr = 0x7E820000"); // Location in AP address space where CTI that connects to the core is located
  //
  // Use AXI-AP for background memory accesses (RTT / HSS)
  //
  JLINK_ExecCommand("CORESIGHT_SetIndexBGMemAPToUse = 1");
  return 0;
}

Note: When selecting an officially supported device (manufacturer + name) in the J-Link software and not a generic Cortex-A/R entry, J-Link usually has a compiled-in script for that particular device, that already specifies the AP to be used for RTT. In such cases, no script file is needed. Please refer to the appropriate device specifics wiki article for more information if a particular device supports RTT.

HSS support

See section RTT support

Debugging through execution state changes

The ARMv8-A/R architecture describes 2 execution states:

  • AArch64
  • AArch32

An execution state change can only happen when changing the exception level (EL0-EL3).
While J-Link supports debugging through code that changes between AArch32 and AArch64, most debuggers / IDEs do not. For example with GDB it is not possible to debug an application that contains AArch32 and AArch64 code because the register set as well as the instruction set changes with the execution state, which is problematic.

EL2 registers

If exception level 2 (EL2) is implemented (this is an optional exception level), there are some registers that are specific to EL2.
If EL2 runs in AArch32 execution state:

  • ELR_hyp
  • HSR
  • SPSR_hyp

If EL2 runs in AArch64 execution state:

  • ELR_EL2
  • ESR_EL2
  • SPSR_EL2

The above mentioned registers are mapped to each other (so they only exist once in hardware).

Note:
  • The EL2 registers are only accessible if the core is in EL2 or higher. For example if the core is halted in EL1, they cannot be written / read by J-Link.
    If J-Link would temporarily change to EL2 to read them, the EL switch would cause the register values to become invalid / unknown (by ARMv8-A/R architecture definition).
  • If a debugger requests these registers while the core is below EL2 mode, J-Link will return all 0s for them.

Vector catch support

For ARMv8-A/R, vector catch does not generate a halt request to the core (entry to Debug state)
but instead generates a debug exception that jumps to the debug exception handler.
Vector catch is designed for self-hosted debug (e.g. debugging an application under a Linux OS running on the chip and without an external debug probe).
Therefore, vector catch is not available when debugging with J-Link.

Device Support

J-Link has general support for the ARMv8-A/R architecture. This means Cortex-A53, A55, A72, ... cores are supported.

However, here is the pitfall: For most v8-A/R based devices you need special connect, reset, ... sequences so just because the core is supported does not necessarily mean that the device is working out-of-the box. You may need to create a J-Link script file as long as we do not list a particular device as being supported: https://www.segger.com/supported-devices/jlink/

This comes as no surprise. Most vendors design these big devices with the goal to have a Linux running on it. The documentation about the debug interface is next to no-existent. Last but not least, as most people are running a Linux on such devices, they don‘t need a debug probe at all.