Difference between revisions of "Semihosting"

From SEGGER Wiki
Jump to: navigation, search
m (ARM Cortex devices: BKPT)
m (ARM Cortex devices: BKPT)
Line 48: Line 48:
   
 
==== ARM Cortex devices: BKPT====
 
==== ARM Cortex devices: BKPT====
A breakpoint is used to hold the CPU. The debug agent recognizes that this is a request for semihosting, not a "regular breakpoint" because:
+
A breakpoint is used to hold the CPU. The debug agent recognizes that this is a request for semihosting, not a "regular breakpoint" because it is a breakpoint that has not been set by the debug agent, and there are 2 implementations for it, for ARM or THUMB mode.
it is a breakpoint that has not been set by the debug agent, and there are 2 implementations for it, for ARM or THUMB mode.
 
 
=====Thumb mode=====
 
=====Thumb mode=====
 
If implemented in Thumb mode, the instruction used is
 
If implemented in Thumb mode, the instruction used is

Revision as of 14:55, 3 July 2019

Semihosting is a mechanism that enables code running on an Embedded System (also called the target) to communicate with and use the I/O of the host computer.

Operations

Semihosting allows use of some of the host's resources, such as terminal I/O, File I/O and access to Real time. Not all operations are supported by all implementations, and some are actually a security hazard, therefore potentially not implemented.

Semihosting operations defined by ARM

ARM has defined 24 semihosting operations. Not all of these really make sense in an Embedded System. Below is the list of operations as defined by ARM, in alphabetic order, along with the function number assigned:

File operations

  • SYS_CLOSE (0x2) - Closes a file on the host which has been opened by SYS_OPEN.
  • SYS_ERRNO (0x13) - Returns the value of the C library errno variable that is associated with the semihosting implementation.
  • SYS_FLEN (0x0C)

Target time

These functions are not typically needed and implemented.

  • SYS_CLOCK (0x10) - Returns target execution time in centiseconds (10ms). Not normally used.
  • SYS_ELAPSED (0x30) - Returns the number of elapsed target ticks since execution started.

Obsolete

  • SYS_EXIT (0x18)
  • SYS_EXIT_EXTENDED (0x20)

Common semihosting operations

A de-facto standard for semihosting operations has been defined by ARM. This, but now widely adopted, defining the "Common semihosting operations".
Semihosting has been around for a very long time. It was not invented by ARM.

Basic operation

Basically, the target CPU is halted, either by running into a breakpoint instruction or by some other operation which stops program execution and puts the target CPU under control of the debug-agent.
The debug agent can be either the debug probe (e.g. J-Link) or the debugger (such as GDB, SEGGER Ozone or the debugger integrated in Embedded Studio). The debug agent reads one or more register(s) to determine the type of operation to be performed by the host on behalf of the target, then performs the action, then restarts the target. The target is halted for the duration of the semihosting operation.

Ways to halt the target CPU

There are different ways to halt the target CPU, primarily special calls such as "Supervisor calls" or Breakpoints. Ideally, an implementation of semihosting is done in a way that when the system does not run under control of a debugger, it still works. This is really important for systems which use semihosting for things that are optional, not essential, such as debug output (printf) to the host. For example, ARM's Cortex-M implementation has the following problem: It uses a breakpoint instruction, which leads to a hard fault if the CPU is not running in debug mode. The way to handle this is using a special hardfault handler, which checks the source of the problem, and allows "skipping" of the BKPT instruction and resumption of program execution.

Implementation on different CPUs

ARM legacy cores (ARM7, ARM9, ARM11): SVC call

Older ARM cores, such as ARM7, ARM9 and ARM11, used an SVC call for semihosting. Typically, the debug agent will set a break point or use vector catch to hold the CPU once it enters the SVC mode, then perform the host action and continue execution. In ARM Mode, the following instruction is used:

SVC 0x123456

in Thumb mode, the same instruction is used but with another parameter. As in thumb mode the parameter is limited to 8 bits:

SVC 0x123456

See also http://www.keil.com/support/man/docs/armcc/armcc_pge1358787048379.htm

ARM Cortex devices: BKPT

A breakpoint is used to hold the CPU. The debug agent recognizes that this is a request for semihosting, not a "regular breakpoint" because it is a breakpoint that has not been set by the debug agent, and there are 2 implementations for it, for ARM or THUMB mode.

Thumb mode

If implemented in Thumb mode, the instruction used is

BKPT 0xAB

In Thumb mode, a 16-bit instruction space is used for the breakpoint, with one byte being used to recognize the breakpoint instruction, and the other one not being used, so available as parameter. 0xAB as second byte or parameter marks it as breakpoint for the purpose of semihosting. Cortex-M device always run in Thumb mode (Thumb-2), therefor always use this instruction.

ARM mode

If implemented in ARM mode, the instruction used is

BKPT 0x123456

In ARM mode, a 32-bit instruction space is used for the breakpoint, with one bytes being used to recognize the breakpoint instruction, and the remaining 3 available as parameter. 0x123456 as parameter marks it as breakpoint for the purpose of semihosting.

RISC-V

At this point, there is no clear standard for RISC-V semihosting. The big problem is that there is not equivalent of a Supervisor call or breakpoint with parameter, and that the behavior of the CPU is not clearly defined when hitting a breakpoint in non-debug mode and is therefor non-recoverable. More to come, please contact SEGGER for up to date information.

Using Semihosting with J-Link

Semihosting with Embedded Studio

The implementation of semihosting in Embedded Studio is straight forward. Standard library functions for fopen, fwrite, fread etc. are already implemented and just need to be called. It is recommended to use the project wizard when creating a new project so all default settings are set correctly.

The following example project opens a file on your host system and writes a string into it triggered by your target device: Semihosting Embedded Studio

Make sure the file path is existing otherwise the project will not run. You can of course change the path by simply editing variable pFilename and rebuild it with Embedded Studio.

Prerequisites for the example project are:

  • Embedded Studio V4.16 or later
  • Cortex-M Trace Reference Board (ST STM32F407VE)
  • J-Link V10 or later

Baremetal Semihosting with Ozone

Ozone is a debugger so it does not come with standard libraries and predefined semihosting code like it does with some IDEs. Thus to make use of semihosting the semihosting calls need to be implemented manually by the user in the target application. The big benefit of this approach without predefined library functions is that you get full control about the complexity of the semihosting implementation so you can write more efficient code as the library overhead is missing.

A baremetal example implementation can be found in the following example project: Semihosting Ozone

The example project will open a file on the host system and write a string to it. Make sure the file path is existing otherwise the project will not run. You can of course change the path by simply editing variable pFilename and rebuild it with Embedded Studio.

Prerequisites for the example project are:

  • Ozone V2.62 or later
  • Embedded Studio V4.16 or later
  • Cortex-M Trace Reference Board (ST STM32F407VE)
  • J-Link V10 or later

This baremetal code can be used with any debug software which supports semihosting handling.

Semihosting with newlib and GNU Arm toolchain

This section will cover how semihosting can be used with Eclipse in combination with GDB and newlib. Generally newlib will only provide a rudimentary setup for semihosting so it will not work out-of-thebox except for printf calls. All callbacks used by e.g. fopen need to be implemented by the user to utilize semihosting.

The following project will show such an example project and create a file at a certain path, fill it with a string and close that file: Semihosting Eclipse

Make sure the file path is existing otherwise the project will not run. You can of course change the path by simply editing variable pFilename and rebuild it with Eclipse. As a base project a default J-Link debug project was created for Cortex-M. Then a debug config with the correct target device was set up. Next make sure that in the debug config semihosting is enabled.

The example project comes also with an Ozone setup that runs out-of-the-box should Eclipse not be the debugger of your choice.

Prerequisites for the example project are:

  • Eclipse Cpp 2019-03
  • Latest GNU ARM Eclipse plugin
  • Cortex-M Trace Reference Board (ST STM32F407VE)
  • J-Link V10 or later
  • (optional) Ozone V2.62 or later

Semihosting with EWARM

The implementation of semihosting in EWARM is generally available but requires some extra settings in your project. Standard library functions for fopen, fwrite, fread etc. are implemented and just need to be called. Under project options semihosting must be enabled as well as the library support must be set to "full" which will drastically increase memory usage of your project.

The project options can be found at the following project settings:

EWARM Library setting.png

Set the library level to "Full" and the library low level implementation to semihosting each.

Note: This will also increase your application size immensely so make sure your target device has enough memory resources left.

The following example project opens a file on your host system and writes a string into it triggered by your target device: Semihosting EWARM

Make sure the file path is existing otherwise the project will not run. You can of course change the path by simply editing variable pFilename and rebuild it with Embedded Studio.

Prerequisites for the example project are:

  • EWARM V8.322 or later
  • Cortex-M Trace Reference Board (ST STM32F407VE)
  • J-Link V10 or later