Difference between revisions of "Semihosting with Ozone"

From SEGGER Wiki
Jump to: navigation, search
m (References)
(Semihosting via SVC on Cortex-A/R)
Line 101: Line 101:
 
<code>Project.ConfigSemihosting("Vector=<address>")</code>.
 
<code>Project.ConfigSemihosting("Vector=<address>")</code>.
   
Note that the letter option has no effect on ARM9 targets, as is explained below.
+
Note that these options have no effect on ARM9 targets, as is explained below.
   
 
== Semihosting with Ozone on Legacy-Arm ==
 
== Semihosting with Ozone on Legacy-Arm ==

Revision as of 12:02, 9 July 2019

Overview

Semihosting is the name of a communication protocol which provides an embedded target access to Host-PC resources. This article assumes that the reader is familiar with the technical aspects of semihosting. The focus of this article lies on the configuration and usage of semihosting within Ozone.

Supported Architectures

Ozone supports semihosting on the following target architectures:

  • Cortex-M (<= v8)
  • Cortex-A/R (<= v8)
  • legacy-ARM

Terminal Window

All semihosting communication between the target and Ozone is logged to Ozone's terminal window. Terminal window contents can be routed to a session log file using command Project.SetTerminalLogFile. Ozone will also inform about the status of the current semihosting operation within its status bar. A typical status text may read Performing semihosting operation SysRead....

Enabling Semihosting

SemihostingCaptureIO.png

Semihosting awareness is enabled target-independently via command Project.SetSemihosting(1) or by checking the Terminal Window’s context menu item Capture Semihosting IO (see illustration on the right). When semihosting awareness is switched off, Ozone will not detect nor respond to semihosting halts of the embedded target and the target might be halting forever.

Semihosting with Ozone on Cortex-M

The debuggee signals a semihosting request to Ozone by executing the semihosting trap instruction BKPT #0xAB with encoding 0xBABC. Before executing the trap, the debuggee loads the semihosting operation type to register R0, and the semihosting argument pointers to registers R1 and R2, where they are exposed to the debugger. Once Ozone has finished processing the request, it will write the operation result code to register R0 and resume the debuggee.

A code example of a client function which triggers a semihosting operation on the Host-PC and returns its result code is shown below.

int ExecuteSemihostingOperation(int op, void* p1, void* p2) {
  register int r0 asm(r0);
  register int r1 asm(r1) __attribute__((unused));
  register int r2 asm(r2) __attribute__((unused));

  r0 = op;
  r1 = (int) p1;
  r2 = (int) p2;

  asm volatile(
       BKPT 0xAB \n
      : =r(r0) // out
      : // in
      : // clobber
  );
  return r0;

Semihosting with Ozone on Cortex-A/R

The debugeee signals a semihosting request to Ozone by executing any of the 5 semihosting trap instructions:

In A64 execution state:

  • HLT #0xF000 with encoding 0xD45E0000.

In A32 execution state:

  • SVC #0x123456 with encoding 0xEF123456.
  • HLT #0xF000 with encoding 0xE10F0070.

In T32 execution state:

  • SVC #0xAB with encoding 0xDFAB.
  • HLT #0x3C with encoding 0xBABC.

Before executing the trap, the debuggee loads the semihosting operation type to register R0, and the semihosting argument pointers to registers R1 and R2, where they are exposed to the debugger. Once Ozone has finished processing the request, the debugger will write the operation result code to register R0 and resume the debuggee. A semihosting request induced by the HLT instruction is similar to a BKPT-induced request on Cortex-M. Identical considerations apply regarding the avoidance of lockups and deadlocks.

Semihosting via SVC on Cortex-A/R

When semihosting is in its default configuration state and enabled, Ozone will set a hardware breakpoint on the SVC instruction at address 0x8 in order to catch semihosting requests. This default behavior can reduce the run-time performance of clients which make extensive use of software interrupts.

Ozone provides two configuration options to alleviate this problem:

  • Ozone can be told that the debuggee is only using HLT-type semihosting traps. In this case, Ozone will not set any hardware breakpoint when semihosting is enabled.
  • The trap instruction can be configured to an arbitrary address within the SVC handler. This way, developers get the chance to evaluate the SWI opcode within the SVC handler on the target side. The handler code is expected to execute the trap instruction (breakpointed by Ozone) only when the SWI opcode matches a semihosting SWI opcode. When this option is employed, developers have to make sure that the semihosting opcode and argument pointer registers R0, R1 and R2 are not modified within SVC handler code up to the point where the semihosting trap instruction is executed.

The first of the options outlined above is set using command;

Project.ConfigSemihosting("UsesSVC=0")

the latter option is set using command:

Project.ConfigSemihosting("Vector=<address>").

Note that these options have no effect on ARM9 targets, as is explained below.

Semihosting with Ozone on Legacy-Arm

The debugeee signals a semihosting request to Ozone by executing any of the 2 semihosting trap instructions:

In A32 execution state:

  • SVC #0x123456 with encoding 0xEF123456.

In T32 execution state:

  • SVC #0xAB with encoding 0xDFAB.

Before executing the trap, the debuggee loads the semihosting operation type to register R0, and the semihosting argument pointers to registers R1 and R2, where they are exposed to the debugger. Once Ozone has finished processing the request, the debugger will write the operation result code to register R0 and resume the debuggee. A semihosting request induced by the HLT instruction is similar to a BKPT-induced request on Cortex-M. Identical considerations apply regarding the avoidance of lockups and deadlocks.

Semihosting via SVC on Legacy-ARM

Semihosting via SVC on legacy Arm is performed identically to the implementation on Cortex-A/R, as described above, with the following exception: On ARM9 targets, Ozone does not set a hardware breakpoint. The debugger instead sets a vector catch on SVC in order to catch semihosting requests. This also means that command Project.ConfigSemihosting("Vector=<address>") has no effect on ARM9.

Supported Operations

Ozone currently supports the following legacy semihosting operations as defined by Arm. It is possible to extend the list of supported operations with custom definitions in the future.

  • SysOpen
  • SysClose
  • SysWriteC
  • SysWrite0
  • SysWrite
  • SysRead
  • SysReadC
  • SysIsError
  • SysIsTty
  • SysSeek
  • SysFlen
  • SysClock
  • SysTime
  • SysErrno
  • SysGetCmdLine
  • SysHeapInfo
  • SysExit

The following legacy operations are currently not supported for security reasons:

  • SysTmpNam
  • SysRemove
  • SysRename
  • SysSystem

For further information on these operations, including their opcode and parameter definitions, see references.

User Input Operations

Ozone supports the following semihosting user input operations:

  • SysReadC and
  • SysRead with IsTtyHandle(R1)==1

These operations will block the client task until a text is input into Ozone's terminal window prompt. When a text was input, Ozone returns the integer result code <NumBytesRequested> - <NumBytesInput> to the debuggee via register R0 and resumes the debuggee.

Frame

General Considerations When Using Semihosting

Avoiding Exceptions

Depending on the architecture, a target might produce an exception or go in to lockup if it executes a semihosting trap instruction while a debugger is not attached. It is therefore generally a good strategy to maintain the debugger connection status in a variable and only execute the trap when the debugger is connected. As an example, On Cortex-M the connection status can be read from system register DHCSR.

Avoiding Deadlocks

Client developers also have to be aware of the fact that a semihosting operation will block the requesting task for a possibly very long period of time. The debugger might even run into an error or disconnect while executing a semihosting operation, leaving the debuggee in a blocked state. To avoid a deadlock in this situations, a robust client implementation can set up a watchdog to resume itself from a semihosting trap on timeout.

References

Standard technical references on semihosting:

  • ARM info center, What is Semihosing?

Ozone-specific semihosting resources:

  • SEGGER Wiki article on Semihosting [[1]]
  • Ozone user guide, section Terminal IO