Client API
Header: zbc_client.h
The client API provides functions for guest/embedded code to make semihosting calls to the host system.
Types
-
type zbc_client_state_t
Client state structure.
Initialize with zbc_client_init() before use.
-
type zbc_response_t
Response from a semihosting call.
Populated by zbc_call() and zbc_parse_response().
Initialization
-
void zbc_client_init(zbc_client_state_t *state, volatile void *dev_base)
Initialize client state with device base address.
The function detects the platform’s integer size, pointer size, and endianness automatically using compile-time configuration macros.
- Parameters:
state – Client state structure to initialize
dev_base – Memory-mapped device base address
-
int zbc_client_check_signature(const zbc_client_state_t *state)
Check if a semihosting device is present by reading the signature.
Call this before making semihosting calls to verify the device exists.
- Parameters:
state – Initialized client state
- Returns:
ZBC_OK if device signature matches “SEMIHOST”, ZBC_ERR_NULL_ARG if state or dev_base is NULL, ZBC_ERR_DEVICE_ERROR if signature mismatch
-
void zbc_client_reset_cnfg(zbc_client_state_t *state)
Reset the CNFG sent flag, forcing resend on next call.
Normally the CNFG chunk is sent only once. Use this if you need to resend configuration (e.g., after device reset).
- Parameters:
state – Initialized client state
Making Calls
-
int zbc_call(zbc_response_t *response, zbc_client_state_t *state, void *buf, size_t buf_size, int opcode, uintptr_t *args)
Execute a semihosting syscall.
This is the main entry point for making semihosting calls. The function: 1. Builds a RIFF request from the opcode table 2. Submits the request to the device (synchronous) 3. Parses the response into the response structure
On success, check response->result for the syscall return value and response->error_code for the host errno.
- Parameters:
response – Receives parsed response (result, errno, data pointer)
state – Initialized client state
buf – RIFF buffer (caller-provided)
buf_size – Size of buffer in bytes
opcode – SH_SYS_* opcode from zbc_protocol.h
args – Array of arguments (layout depends on opcode), may be NULL
- Returns:
ZBC_OK on success, ZBC_ERR_* on protocol/transport error
Example:
zbc_response_t response;
uintptr_t args[1];
args[0] = (uintptr_t)"Hello\n";
int rc = zbc_call(&response, &client, buf, sizeof(buf),
SH_SYS_WRITE0, args);
if (rc != ZBC_OK) {
/* Protocol error */
}
-
uintptr_t zbc_semihost(zbc_client_state_t *state, uint8_t *riff_buf, size_t riff_buf_size, uintptr_t op, uintptr_t param)
ARM-compatible semihost entry point.
This is a thin wrapper around zbc_call() that accepts the ARM-style parameter block format (op, pointer-to-args) used by picolibc and newlib.
Use this to implement sys_semihost() for libc integration.
- Parameters:
state – Initialized client state
riff_buf – RIFF buffer
riff_buf_size – Size of buffer
op – SH_SYS_* opcode
param – Pointer to args array (cast from uintptr_t*)
- Returns:
Syscall result, or (uintptr_t)-1 on error
Use this to implement sys_semihost() for libc integration:
uintptr_t sys_semihost(uintptr_t op, uintptr_t param)
{
return zbc_semihost(&client, riff_buf, sizeof(riff_buf), op, param);
}
Low-Level Functions
-
int zbc_client_submit(zbc_client_state_t *state, void *buf, size_t size)
Submit a RIFF request to the semihosting device.
This writes the buffer address to RIFF_PTR and triggers DOORBELL. The host processes the request synchronously - when this function returns, the response is already in the RIFF buffer. Most users should use zbc_call() instead.
- Parameters:
state – Initialized client state
buf – RIFF buffer containing the request
size – Size of request data
- Returns:
ZBC_OK on success, error code on failure
-
int zbc_parse_response(zbc_response_t *response, const uint8_t *buf, size_t capacity, const zbc_client_state_t *state)
Parse response from RIFF buffer.
Extracts the result, errno, and data from a RETN or ERRO chunk. Most users should use zbc_call() instead.
- Parameters:
response – Receives parsed response
buf – RIFF buffer containing the response
capacity – Buffer capacity
state – Client state (for int_size/endianness)
- Returns:
ZBC_OK on success, ZBC_ERR_PARSE_ERROR on failure
Configuration Macros
These macros can be overridden at compile time to configure the client for non-standard platforms:
ZBC_CLIENT_INT_SIZESize of
intin bytes. Default:sizeof(int)ZBC_CLIENT_PTR_SIZESize of pointers in bytes. Default:
sizeof(void *)ZBC_CLIENT_ENDIANNESSEndianness (
ZBC_ENDIAN_LITTLEorZBC_ENDIAN_BIG). Default: detected from__BYTE_ORDER__