Difference between revisions of "SEGGER Semihosting"
m |
m (→Interface) |
||
(5 intermediate revisions by 2 users not shown) | |||
Line 11: | Line 11: | ||
The reference project is available for download here: |
The reference project is available for download here: |
||
[[Media:SEGGER_SEMIHOST_Generic.zip|sources]] |
[[Media:SEGGER_SEMIHOST_Generic.zip|sources]] |
||
+ | |||
+ | == Implementation == |
||
+ | All public functions can be called by the application. They usually package the parameters, then call SEGGER_SEMIHOST_X_Request(), |
||
+ | which either implements some kind of a breakpoint / halt / Supervisor call instruction (if available for the target) or simply call |
||
+ | SEGGER_SEMIHOST_DebugHalt(), which is a function that the debugger automatically sets a break point on. |
||
+ | So a typical call stack for a simple hello world application would be as follows: |
||
+ | main() |
||
+ | SEGGER_SEMIHOST_Writef() |
||
+ | SEGGER_SEMIHOST_X_Request() |
||
+ | SEGGER_SEMIHOST_DebugHalt() |
||
+ | |||
+ | The implementation of the functions is quite simple, which means the code overhead of Semihosting is very small: |
||
+ | |||
+ | === SEGGER_SEMIHOST_Writef === |
||
+ | <syntaxhighlight lang="c"> |
||
+ | /********************************************************************* |
||
+ | * |
||
+ | * SEGGER_SEMIHOST_Writef() |
||
+ | * |
||
+ | * Function description |
||
+ | * Write a formatted string to debug channel on the host system. |
||
+ | * The string is formatted on the host. |
||
+ | * |
||
+ | * Parameters |
||
+ | * pFormat: Pointer to string to be formatted and printed. |
||
+ | * aArg: Arguments |
||
+ | * |
||
+ | * Return value |
||
+ | * = -1: Error. |
||
+ | * >= 0: OK. Number of bytes printed. |
||
+ | * |
||
+ | * Additional information |
||
+ | * int myprintf(const char* s, ...) { |
||
+ | * va_list List; |
||
+ | * |
||
+ | * va_start(List, s); |
||
+ | * SEGGER_SEMIHOST_Writef(s, &List); |
||
+ | * va_end(List); |
||
+ | * |
||
+ | * return 0; |
||
+ | * } |
||
+ | * |
||
+ | */ |
||
+ | int SEGGER_SEMIHOST_Writef(const char* pFormat, va_list* pArg) { |
||
+ | SEGGER_SEMIHOST_PARA aPara[2]; |
||
+ | int r; |
||
+ | |||
+ | aPara[0].cpC = pFormat; |
||
+ | aPara[1].pV = (void*)pArg; |
||
+ | r = SEGGER_SEMIHOST_X_Request(SYS_WRITEF, aPara); |
||
+ | |||
+ | return r; |
||
+ | } |
||
+ | </syntaxhighlight> |
||
+ | |||
+ | === SEGGER_SEMIHOST_X_Request() === |
||
+ | <syntaxhighlight lang="c"> |
||
+ | /********************************************************************* |
||
+ | * |
||
+ | * SEGGER_SEMIHOST_X_Request() |
||
+ | * |
||
+ | * Function description |
||
+ | * Notify the debugger host about the semihosting request |
||
+ | * |
||
+ | * Parameters |
||
+ | * Op: Operation. |
||
+ | * pPara: Pointer to parameter block. |
||
+ | * |
||
+ | * Return value |
||
+ | * Operation-specific return value, set by the debugger in R0. |
||
+ | */ |
||
+ | int SEGGER_SEMIHOST_X_Request(int Op, SEGGER_SEMIHOST_PARA* pPara) { |
||
+ | int r0; |
||
+ | |||
+ | r0 = SEGGER_SEMIHOST_DebugHalt((int)Op, (int)pPara); |
||
+ | |||
+ | return r0; |
||
+ | }</syntaxhighlight> |
||
+ | |||
+ | === SEGGER_SEMIHOST_DebugHalt() === |
||
+ | <syntaxhighlight lang="c"> |
||
+ | /********************************************************************* |
||
+ | * |
||
+ | * SEGGER_SEMIHOST_DebugHalt() |
||
+ | * |
||
+ | * Function description |
||
+ | * Dummy call for generic implementation. |
||
+ | * The debugger may set a breakpoint on this function, |
||
+ | * handle the semihosting request, |
||
+ | * and return to the caller. |
||
+ | * |
||
+ | * Return value |
||
+ | * Return parameter r0 if debugger is not connected. |
||
+ | */ |
||
+ | int __attribute__((noinline)) SEGGER_SEMIHOST_DebugHalt(int r0, int r1) { |
||
+ | (void)r1; // Avoid unused parameter warning |
||
+ | return r0; |
||
+ | } |
||
+ | </syntaxhighlight> |
||
== Interface== |
== Interface== |
||
Line 40: | Line 139: | ||
int SEGGER_SEMIHOST_Exit (int ExitCode); |
int SEGGER_SEMIHOST_Exit (int ExitCode); |
||
int SEGGER_SEMIHOST_IsConnected (void); |
int SEGGER_SEMIHOST_IsConnected (void); |
||
+ | int SEGGER_SEMIHOST_X_Request (int Op, SEGGER_SEMIHOST_PARA* pPara); |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
− | |||
− | int SEGGER_SEMIHOST_X_Request (int Op, SEGGER_SEMIHOST_PARA* pPara); |
Latest revision as of 11:14, 5 September 2019
SEGGER Semihosting is a standard for Semihosting, defined by SEGGER and compatible to an older standard defined by ARM.
Contents
File structure of reference implementation
The reference implementation is provided as a ZIP file, containing a complete project for SEGGER Embedded Studio. The relevant sources are 3 files which are completely generic, so can be compiled on any system using any C- compiler:
- SEGGER_SEMIHOST.h - Interface definition
- SEGGER_SEMIHOST.c - Implementation of the Semihosting interface functions
- SEGGER_SEMIHOST_Generic.c - Implementation of the SEGGER_SEMIHOST_X_Request routine to call SEGGER_SEMIHOST_DebugHalt
The reference project is available for download here: sources
Implementation
All public functions can be called by the application. They usually package the parameters, then call SEGGER_SEMIHOST_X_Request(), which either implements some kind of a breakpoint / halt / Supervisor call instruction (if available for the target) or simply call SEGGER_SEMIHOST_DebugHalt(), which is a function that the debugger automatically sets a break point on. So a typical call stack for a simple hello world application would be as follows:
main() SEGGER_SEMIHOST_Writef() SEGGER_SEMIHOST_X_Request() SEGGER_SEMIHOST_DebugHalt()
The implementation of the functions is quite simple, which means the code overhead of Semihosting is very small:
SEGGER_SEMIHOST_Writef
/*********************************************************************
*
* SEGGER_SEMIHOST_Writef()
*
* Function description
* Write a formatted string to debug channel on the host system.
* The string is formatted on the host.
*
* Parameters
* pFormat: Pointer to string to be formatted and printed.
* aArg: Arguments
*
* Return value
* = -1: Error.
* >= 0: OK. Number of bytes printed.
*
* Additional information
* int myprintf(const char* s, ...) {
* va_list List;
*
* va_start(List, s);
* SEGGER_SEMIHOST_Writef(s, &List);
* va_end(List);
*
* return 0;
* }
*
*/
int SEGGER_SEMIHOST_Writef(const char* pFormat, va_list* pArg) {
SEGGER_SEMIHOST_PARA aPara[2];
int r;
aPara[0].cpC = pFormat;
aPara[1].pV = (void*)pArg;
r = SEGGER_SEMIHOST_X_Request(SYS_WRITEF, aPara);
return r;
}
SEGGER_SEMIHOST_X_Request()
/*********************************************************************
*
* SEGGER_SEMIHOST_X_Request()
*
* Function description
* Notify the debugger host about the semihosting request
*
* Parameters
* Op: Operation.
* pPara: Pointer to parameter block.
*
* Return value
* Operation-specific return value, set by the debugger in R0.
*/
int SEGGER_SEMIHOST_X_Request(int Op, SEGGER_SEMIHOST_PARA* pPara) {
int r0;
r0 = SEGGER_SEMIHOST_DebugHalt((int)Op, (int)pPara);
return r0;
}
SEGGER_SEMIHOST_DebugHalt()
/*********************************************************************
*
* SEGGER_SEMIHOST_DebugHalt()
*
* Function description
* Dummy call for generic implementation.
* The debugger may set a breakpoint on this function,
* handle the semihosting request,
* and return to the caller.
*
* Return value
* Return parameter r0 if debugger is not connected.
*/
int __attribute__((noinline)) SEGGER_SEMIHOST_DebugHalt(int r0, int r1) {
(void)r1; // Avoid unused parameter warning
return r0;
}
Interface
The below is an exert from SEGGER_SEMIHOST.h, containg the API of the the SEGGER implementation.
int SEGGER_SEMIHOST_Open (const char* sFilename, int Mode, int LenFilename);
int SEGGER_SEMIHOST_Close (int hFile);
int SEGGER_SEMIHOST_WriteC (char c);
int SEGGER_SEMIHOST_Write0 (const char* s);
int SEGGER_SEMIHOST_Write (int hFile, const char* pBuffer, int NumBytesToWrite);
int SEGGER_SEMIHOST_Writef (const char* pFormat, va_list* pArg);
int SEGGER_SEMIHOST_Read (int hFile, char* pBuffer, int NumBytesToRead);
int SEGGER_SEMIHOST_ReadC (void);
int SEGGER_SEMIHOST_IsTTY (int hFile);
int SEGGER_SEMIHOST_Seek (int hFile, int Pos);
int SEGGER_SEMIHOST_FLen (int hFile);
int SEGGER_SEMIHOST_TmpName (char* pBuffer, int hFile, int pNumBytesName);
int SEGGER_SEMIHOST_Remove (const char* pPath, int NumBytesPath);
int SEGGER_SEMIHOST_Rename (const char* pFileName, int NumBytesFileName, const char* pNewName, int NumBytesNewName);
int SEGGER_SEMIHOST_Clock (void);
int SEGGER_SEMIHOST_Time (void);
int SEGGER_SEMIHOST_System (const char* pCommand, int NumBytesCommand);
int SEGGER_SEMIHOST_Errno (void);
int SEGGER_SEMIHOST_GetCmdLine (char* pBuffer, char** psCmdLine, int* pNumBytesCmdLine);
int SEGGER_SEMIHOST_Elapsed (unsigned long long* pTicks);
int SEGGER_SEMIHOST_HeapInfo (char* pDataBlock);
int SEGGER_SEMIHOST_TickFreq (void);
int SEGGER_SEMIHOST_Exit (int ExitCode);
int SEGGER_SEMIHOST_IsConnected (void);
int SEGGER_SEMIHOST_X_Request (int Op, SEGGER_SEMIHOST_PARA* pPara);