From c0df348156f3fa55cdf35ebce27b8f53bc1c4006 Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Thu, 10 Mar 2022 11:44:42 +0100 Subject: [PATCH 1/2] semihosting: version 2 --- components/riscv/include/riscv/semihosting.h | 33 ++--------- components/vfs/openocd_semihosting.h | 56 +++++++++++++++++-- components/vfs/vfs_semihost.c | 18 ------ .../xtensa/include/xtensa/semihosting.h | 47 ++-------------- 4 files changed, 61 insertions(+), 93 deletions(-) diff --git a/components/riscv/include/riscv/semihosting.h b/components/riscv/include/riscv/semihosting.h index d5402964b0..5330161d72 100644 --- a/components/riscv/include/riscv/semihosting.h +++ b/components/riscv/include/riscv/semihosting.h @@ -19,7 +19,7 @@ extern "C" { * @param addr address of apptrace control data block * @return return 0 on sucess or non-zero error code */ -#define ESP_SEMIHOSTING_SYS_APPTRACE_INIT 0x64 +#define ESP_SEMIHOSTING_SYS_APPTRACE_INIT 0x101 /** * @brief Initialize debug stubs table at host side @@ -27,7 +27,7 @@ extern "C" { * @param addr address of debug stubs table * @return return 0 on sucess or non-zero error code */ -#define ESP_SEMIHOSTING_SYS_DBG_STUBS_INIT 0x65 +#define ESP_SEMIHOSTING_SYS_DBG_STUBS_INIT 0x102 /** * @brief Set/clear breakpoint @@ -37,7 +37,7 @@ extern "C" { * @param addr address to set breakpoint at. Ignored if `set` is false. * @return return 0 on sucess or non-zero error code */ -#define ESP_SEMIHOSTING_SYS_BREAKPOINT_SET 0x66 +#define ESP_SEMIHOSTING_SYS_BREAKPOINT_SET 0x103 /** * @brief Set/clear watchpoint @@ -49,7 +49,7 @@ extern "C" { * @param flags watchpoint flags, see description below. Ignored if `set` is false. * @return return 0 on sucess or non-zero error code */ -#define ESP_SEMIHOSTING_SYS_WATCHPOINT_SET 0x67 +#define ESP_SEMIHOSTING_SYS_WATCHPOINT_SET 0x104 /* bit values for `flags` argument of ESP_SEMIHOSTING_SYS_WATCHPOINT_SET call. Can be ORed. */ /* watch for 'reads' at `addr` */ @@ -85,31 +85,6 @@ static inline long semihosting_call_noerrno(long id, long *data) return a0; } -/** - * @brief Perform semihosting call and retrieve errno - * - * @param id semihosting call number - * @param data data block to pass to the host; number of items and their - * meaning depends on the semihosting call. See the spec for - * details. - * @param[out] out_errno output, errno value from the host. Only set if - * the return value is negative. - * @return return value from the host - */ -static inline long semihosting_call(long id, long *data, int *out_errno) -{ - long ret = semihosting_call_noerrno(id, data); - if (ret < 0) { - /* Constant also defined in openocd_semihosting.h, - * which is common for RISC-V and Xtensa; it is not included here - * to avoid a circular dependency. - */ - const int semihosting_sys_errno = 0x13; - *out_errno = (int) semihosting_call_noerrno(semihosting_sys_errno, NULL); - } - return ret; -} - #ifdef __cplusplus } #endif diff --git a/components/vfs/openocd_semihosting.h b/components/vfs/openocd_semihosting.h index fe829210e8..319df3bd85 100644 --- a/components/vfs/openocd_semihosting.h +++ b/components/vfs/openocd_semihosting.h @@ -66,8 +66,56 @@ extern "C" { * * If the syscall is recognized, the return value is zero. */ -#define SEMIHOSTING_SYS_DRVINFO 0xE0 +#define ESP_SEMIHOSTING_SYS_DRV_INFO 0x100 +/* 0x101...0x104 used by RiscV for custom semihosting calls */ + +/* Other Espressif extension sys calls */ +#define ESP_SEMIHOSTING_SYS_SEEK 0x105 /* custom lseek with whence */ +/* not implemented yet */ +#define ESP_SEMIHOSTING_SYS_MKDIR 0x106 +#define ESP_SEMIHOSTING_SYS_OPENDIR 0x107 +#define ESP_SEMIHOSTING_SYS_READDIR 0x108 +#define ESP_SEMIHOSTING_SYS_READDIR_R 0x109 +#define ESP_SEMIHOSTING_SYS_SEEKDIR 0x10A +#define ESP_SEMIHOSTING_SYS_TELLDIR 0x10B +#define ESP_SEMIHOSTING_SYS_CLOSEDIR 0x10C +#define ESP_SEMIHOSTING_SYS_RMDIR 0x10D +#define ESP_SEMIHOSTING_SYS_ACCESS 0x10E +#define ESP_SEMIHOSTING_SYS_TRUNCATE 0x10F +#define ESP_SEMIHOSTING_SYS_UTIME 0x110 +#define ESP_SEMIHOSTING_SYS_FSTAT 0x111 +#define ESP_SEMIHOSTING_SYS_STAT 0x112 +#define ESP_SEMIHOSTING_SYS_FSYNC 0x113 +#define ESP_SEMIHOSTING_SYS_LINK 0x114 +#define ESP_SEMIHOSTING_SYS_UNLINK 0x115 + +/* Semihosting version bumped to 2. + In this version, memory based approach implemented as defined in the ARM standard. + Also user defined syscall numbers enumerated between 0x100-0x1FF +*/ +#define SEMIHOSTING_DRV_VERSION 2 + +/** + * @brief Perform semihosting call and retrieve errno + * + * @param id semihosting call number + * @param data data block to pass to the host; number of items and their + * meaning depends on the semihosting call. See the spec for + * details. + * @param[out] out_errno output, errno value from the host. Only set if + * the return value is negative. + * @return return value from the host + */ +static inline long semihosting_call(long id, long *data, int *out_errno) +{ + long ret = semihosting_call_noerrno(id, data); + if (ret < 0) { + const int semihosting_sys_errno = SEMIHOSTING_SYS_ERRNO; + *out_errno = (int) semihosting_call_noerrno(semihosting_sys_errno, NULL); + } + return ret; +} static inline int semihosting_open(const char *path, int open_mode, int mode) { @@ -126,7 +174,7 @@ static inline off_t semihosting_seek(int fd, off_t offset, int mode) { int host_errno = 0; long args[] = {fd, offset, mode, 0}; - off_t ret = (off_t) semihosting_call(SEMIHOSTING_SYS_SEEK, args, &host_errno); + off_t ret = (off_t) semihosting_call(ESP_SEMIHOSTING_SYS_SEEK, args, &host_errno); if (ret == -1) { errno = host_errno; } @@ -138,9 +186,9 @@ static inline int semihosting_ver_info(void) int host_errno = 0; struct { int version; - } ver_info = { 1 }; + } ver_info = { SEMIHOSTING_DRV_VERSION }; long args[] = {(long) &ver_info, sizeof(ver_info), 0, 0}; - int ret = (int) semihosting_call(SEMIHOSTING_SYS_DRVINFO, args, &host_errno); + int ret = (int) semihosting_call(ESP_SEMIHOSTING_SYS_DRV_INFO, args, &host_errno); (void) host_errno; /* errno not set by this call */ return ret; } diff --git a/components/vfs/vfs_semihost.c b/components/vfs/vfs_semihost.c index 3dcefd417a..fac48e6907 100644 --- a/components/vfs/vfs_semihost.c +++ b/components/vfs/vfs_semihost.c @@ -109,7 +109,6 @@ static inline bool ctx_uses_abspath(const vfs_semihost_ctx_t* ctx) } \ } while(0) -#if __XTENSA__ static esp_err_t vfs_semihost_drvinfo(vfs_semihost_ctx_t *ctx) { FAIL_IF_NO_DEBUGGER(); @@ -121,7 +120,6 @@ static esp_err_t vfs_semihost_drvinfo(vfs_semihost_ctx_t *ctx) } return ESP_OK; } -#endif // __XTENSA__ static int vfs_semihost_open(void* ctx, const char* path, int flags, int mode) { @@ -160,20 +158,6 @@ static int vfs_semihost_open(void* ctx, const char* path, int flags, int mode) #endif // __XTENSA__ } else { host_path = (char *)path; - /* For Xtensa targets in OpenOCD there is additional logic related to - * semihosting paths handling that isn't there for other targets. - * When ESP_SEMIHOST_BASEDIR OpenOCD variable is not set, OpenOCD will - * by default prepend '.' to the path passed from the target. - * By contrast, for RISC-V there is no such logic and the path will be - * used as is, no matter whether it is absolute or relative. - * See esp_xtensa_semihosting_get_file_name in esp_xtensa_semihosting.c - * for details. - */ -#ifndef __XTENSA__ - if (*host_path == '/') { - ++host_path; - } -#endif // !__XTENSA__ } /* everything is ready: syscall and cleanup */ ret_fd = semihosting_open(host_path, o_mode, mode); @@ -250,13 +234,11 @@ esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path ESP_LOGD(TAG, "Register semihosting driver %d %p", i, &s_semhost_ctx[i]); esp_err_t err; -#if __XTENSA__ /* Check for older OpenOCD versions */ err = vfs_semihost_drvinfo(&s_semhost_ctx[i]); // define semihosting version if (err != ESP_OK) { ESP_LOGE(TAG, "Incompatible OpenOCD version detected. Please follow the getting started guides to install the required version."); } -#endif // __XTENSA__ err = esp_vfs_register(base_path, &vfs, &s_semhost_ctx[i]); if (err != ESP_OK) { diff --git a/components/xtensa/include/xtensa/semihosting.h b/components/xtensa/include/xtensa/semihosting.h index 71a23bb563..8a43605a18 100644 --- a/components/xtensa/include/xtensa/semihosting.h +++ b/components/xtensa/include/xtensa/semihosting.h @@ -10,53 +10,16 @@ extern "C" { #endif -/** - * @brief Perform semihosting call and retrieve errno - * - * @param id semihosting call number - * @param data data block to pass to the host; number of items and their - * meaning depends on the semihosting call. See the spec for - * details. - * On Xtensa, this function assumes that the array contains at - * least 4 elements, but no effort is made to guarantee that. - * Passing a shorter array will still work, as long as it contains - * sufficient values for the corresponding semihosting call. - * @param[out] out_errno output, errno value from the host. Only set if - * the return value is negative. - * @return return value from the host - */ -static inline long semihosting_call(long id, long *data, int *out_errno) // NOLINT(readability-non-const-parameter) +static inline long semihosting_call_noerrno(long id, long *data) { - /* GCC doesn't allow using specific register names in constraints for Xtensa. - * For this case, GCC extended inline assembly manual says the following: - * If you must use a specific register, but your Machine Constraints do not provide - * sufficient control to select the specific register you want, local register variables - * may provide a solution. - * Using local register variables results in simpler generated code than - * the previous implementation which listed a2-a6 as clobbered registers. - */ register long a2 asm ("a2") = id; - register long a3 asm ("a3") = (long) data[0]; - register long a4 asm ("a4") = (long) data[1]; - register long a5 asm ("a5") = (long) data[2]; - register long a6 asm ("a6") = (long) data[3]; + register long a3 asm ("a3") = (long)data; - /* The break instruction operands should be (1, 14) according to the ISA manual. - * We keep (1, 1) for compatibility, until OpenOCD is updated to support both - * conventions. - */ __asm__ __volatile__ ( - "break 1, 1\n" - : "+r"(a2), "+r"(a3) - : "r"(a4), "r"(a5), "r"(a6) + "break 1, 14\n" + : "+r"(a2) : "r"(a3) : "memory"); - - long host_ret = a2; - long host_errno = a3; - if (host_ret < 0) { - *out_errno = host_errno; - } - return host_ret; + return a2; } #ifdef __cplusplus From c55db5e688913d4daa540434b76d417e57a7d4db Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Sun, 13 Mar 2022 19:03:06 +0100 Subject: [PATCH 2/2] semihosting: drop absolute path support --- components/vfs/Kconfig | 9 -- components/vfs/include/esp_vfs_semihost.h | 21 +--- components/vfs/openocd_semihosting.h | 8 +- components/vfs/vfs_semihost.c | 105 ++++++------------ .../xtensa/include/xtensa/semihosting.h | 13 +++ .../restful_server/main/esp_rest_main.c | 2 +- examples/storage/semihost_vfs/README.md | 2 +- .../main/semihost_vfs_example_main.c | 2 +- 8 files changed, 64 insertions(+), 98 deletions(-) diff --git a/components/vfs/Kconfig b/components/vfs/Kconfig index 6b914d8ba3..d3954cb378 100644 --- a/components/vfs/Kconfig +++ b/components/vfs/Kconfig @@ -80,15 +80,6 @@ menu "Virtual file system" default 1 help Define maximum number of host filesystem mount points. - - config VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN - int "Host FS: Maximum path length for the host base directory" - default 128 - help - Define maximum path length for the host base directory which is to be mounted. - If host path passed to esp_vfs_semihost_register() is longer than this value - it will be truncated. - endmenu endmenu diff --git a/components/vfs/include/esp_vfs_semihost.h b/components/vfs/include/esp_vfs_semihost.h index 20a0ed5506..c6db970be7 100644 --- a/components/vfs/include/esp_vfs_semihost.h +++ b/components/vfs/include/esp_vfs_semihost.h @@ -1,16 +1,8 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -24,13 +16,12 @@ extern "C" { * @brief add virtual filesystem semihosting driver * * @param base_path VFS path to mount host directory - * @param host_path host path to mount; if NULL default dirctory will be used (see OpenOCD configuration) * @return * - ESP_OK on success * - ESP_ERR_INVALID_ARG if esp_vfs_semihost_register was already called for specified VFS path * - ESP_ERR_NO_MEM if there are no slots to register new mount point */ -esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path); +esp_err_t esp_vfs_semihost_register(const char* base_path); /** * @brief Un-register semihosting driver from VFS diff --git a/components/vfs/openocd_semihosting.h b/components/vfs/openocd_semihosting.h index 319df3bd85..32dfeb75a9 100644 --- a/components/vfs/openocd_semihosting.h +++ b/components/vfs/openocd_semihosting.h @@ -90,9 +90,11 @@ extern "C" { #define ESP_SEMIHOSTING_SYS_LINK 0x114 #define ESP_SEMIHOSTING_SYS_UNLINK 0x115 -/* Semihosting version bumped to 2. - In this version, memory based approach implemented as defined in the ARM standard. - Also user defined syscall numbers enumerated between 0x100-0x1FF +/* Semihosting version bumped to 2. Changelog; + 1 - Memory based approach with 2 registers implemented as defined in the ARM standard. + 2 - User defined syscall numbers located between 0x100-0x1FF + 3 - The break instruction operands updated to (1, 14) + 4 - Absolute path support is dropped */ #define SEMIHOSTING_DRV_VERSION 2 diff --git a/components/vfs/vfs_semihost.c b/components/vfs/vfs_semihost.c index fac48e6907..2510262225 100644 --- a/components/vfs/vfs_semihost.c +++ b/components/vfs/vfs_semihost.c @@ -28,21 +28,11 @@ #define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1 #endif -#ifndef CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN -#define CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN 128 -#endif - const static char *TAG = "esp_semihost"; /* Additional open flags */ - -/* ESP-specific file open flag. - * Indicates that path passed to open() is absolute host path. - */ -#define ESP_O_SEMIHOST_ABSPATH 0x80000000 - /* There is no O_BINARY flag defined in newlib, as well as on Linux, * but we are leaving it to have the flags table identical to OpenOCD. */ @@ -50,18 +40,18 @@ const static char *TAG = "esp_semihost"; /* The table is identical to the one in OpenOCD semihosting_common.c */ static const int open_modeflags[12] = { - O_RDONLY, - O_RDONLY | O_BINARY, - O_RDWR, - O_RDWR | O_BINARY, - O_WRONLY | O_CREAT | O_TRUNC, - O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, - O_RDWR | O_CREAT | O_TRUNC, - O_RDWR | O_CREAT | O_TRUNC | O_BINARY, - O_WRONLY | O_CREAT | O_APPEND, - O_WRONLY | O_CREAT | O_APPEND | O_BINARY, - O_RDWR | O_CREAT | O_APPEND, - O_RDWR | O_CREAT | O_APPEND | O_BINARY + O_RDONLY, + O_RDONLY | O_BINARY, + O_RDWR, + O_RDWR | O_BINARY, + O_WRONLY | O_CREAT | O_TRUNC, + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, + O_RDWR | O_CREAT | O_TRUNC, + O_RDWR | O_CREAT | O_TRUNC | O_BINARY, + O_WRONLY | O_CREAT | O_APPEND, + O_WRONLY | O_CREAT | O_APPEND | O_BINARY, + O_RDWR | O_CREAT | O_APPEND, + O_RDWR | O_CREAT | O_APPEND | O_BINARY }; /** @@ -86,7 +76,6 @@ static inline int get_o_mode(int flags) { typedef struct { char base_path[ESP_VFS_PATH_MAX + 1]; /* base path in VFS where host semihosting dir is mounted */ - char host_path[CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN + 1]; /* host path to use as base dir for open files */ } vfs_semihost_ctx_t; static vfs_semihost_ctx_t s_semhost_ctx[CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS]; @@ -96,11 +85,6 @@ static inline bool ctx_is_unused(const vfs_semihost_ctx_t* ctx) return ctx->base_path[0] == 0; } -static inline bool ctx_uses_abspath(const vfs_semihost_ctx_t* ctx) -{ - return ctx->host_path[0]; -} - #define FAIL_IF_NO_DEBUGGER() \ do { \ if (!cpu_hal_is_debugger_attached()) { \ @@ -124,46 +108,21 @@ static esp_err_t vfs_semihost_drvinfo(vfs_semihost_ctx_t *ctx) static int vfs_semihost_open(void* ctx, const char* path, int flags, int mode) { int ret_fd = -1; - char *host_path; - vfs_semihost_ctx_t *semi_ctx = ctx; + FAIL_IF_NO_DEBUGGER(); - ESP_LOGV(TAG, "%s: %p '%s 0x%x 0x%x'", __func__, semi_ctx, path, flags, mode); + if (path == NULL) { + errno = ENOENT; + return ret_fd; + } + + ESP_LOGV(TAG, "%s: '%s 0x%x 0x%x'", __func__, path, flags, mode); int o_mode = get_o_mode(flags); if (o_mode == -1) { /* if wrong flags - error */ errno = EINVAL; } else { - if (ctx_uses_abspath(semi_ctx)) { - /* Create full absolute path on the host by concatenating host base - * path and file path relative to the filesystem root. - */ - host_path = malloc(strlen(semi_ctx->host_path) + strlen(path) + 1); - if (host_path == NULL) { /* if no valid pointer - error and return */ - errno = ENOMEM; - return -1; - } - strcpy(host_path, semi_ctx->host_path); - strcat(host_path, path); -#ifdef __XTENSA__ - /* By default, OpenOCD for Xtensa prepends ESP_SEMIHOST_BASEDIR to - * the path passed from the target. Adding this special flag to o_mode - * inhibits this behavior. - * This is not necessary for RISC-V since standard semihosting - * implementation is used there and paths aren't mangled on OpenOCD side. - */ - if (ctx_uses_abspath(semi_ctx)) { - o_mode |= ESP_O_SEMIHOST_ABSPATH; - } -#endif // __XTENSA__ - } else { - host_path = (char *)path; - } - /* everything is ready: syscall and cleanup */ - ret_fd = semihosting_open(host_path, o_mode, mode); - if (ctx_uses_abspath(semi_ctx)) { - free(host_path); - } + ret_fd = semihosting_open(path, o_mode, mode); } return ret_fd; } @@ -172,6 +131,11 @@ static ssize_t vfs_semihost_write(void* ctx, int fd, const void * data, size_t s { FAIL_IF_NO_DEBUGGER(); + if (data == NULL) { + errno = EINVAL; + return -1; + } + ESP_LOGV(TAG, "%s: %d %u bytes", __func__, fd, size); return semihosting_write(fd, data, size); } @@ -180,11 +144,15 @@ static ssize_t vfs_semihost_read(void* ctx, int fd, void* data, size_t size) { FAIL_IF_NO_DEBUGGER(); + if (data == NULL) { + errno = EINVAL; + return -1; + } + ESP_LOGV(TAG, "%s: %d %u bytes", __func__, fd, size); return semihosting_read(fd, data, size); } - static int vfs_semihost_close(void* ctx, int fd) { FAIL_IF_NO_DEBUGGER(); @@ -200,8 +168,10 @@ static off_t vfs_semihost_lseek(void* ctx, int fd, off_t offset, int mode) return semihosting_seek(fd, offset, mode); } -esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path) +esp_err_t esp_vfs_semihost_register(const char* base_path) { + assert(base_path); + const esp_vfs_t vfs = { .flags = ESP_VFS_FLAG_CONTEXT_PTR, .write_p = &vfs_semihost_write, @@ -210,7 +180,7 @@ esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path .read_p = &vfs_semihost_read, .lseek_p = &vfs_semihost_lseek, }; - ESP_LOGD(TAG, "Register semihosting driver '%s' -> '%s'", base_path, host_path ? host_path : "null"); + ESP_LOGD(TAG, "Register semihosting driver '%s'", base_path); if (!cpu_hal_is_debugger_attached()) { ESP_LOGE(TAG, "OpenOCD is not connected!"); return ESP_ERR_NOT_SUPPORTED; @@ -228,9 +198,7 @@ esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path return ESP_ERR_NO_MEM; } strlcpy(s_semhost_ctx[i].base_path, base_path, sizeof(s_semhost_ctx[i].base_path) - 1); - if (host_path) { - strlcpy(s_semhost_ctx[i].host_path, host_path, sizeof(s_semhost_ctx[i].host_path) - 1); - } + ESP_LOGD(TAG, "Register semihosting driver %d %p", i, &s_semhost_ctx[i]); esp_err_t err; @@ -250,6 +218,8 @@ esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path esp_err_t esp_vfs_semihost_unregister(const char* base_path) { + assert(base_path); + ESP_LOGD(TAG, "Unregister semihosting driver @ '%s'", base_path); int i = 0; for (i = 0; i < CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS; i++) { @@ -265,7 +235,6 @@ esp_err_t esp_vfs_semihost_unregister(const char* base_path) return ret; } s_semhost_ctx[i].base_path[0] = 0; - s_semhost_ctx[i].host_path[0] = 0; ESP_LOGD(TAG, "Unregistered semihosting driver @ '%s'", base_path); return ESP_OK; } diff --git a/components/xtensa/include/xtensa/semihosting.h b/components/xtensa/include/xtensa/semihosting.h index 8a43605a18..5849827e7c 100644 --- a/components/xtensa/include/xtensa/semihosting.h +++ b/components/xtensa/include/xtensa/semihosting.h @@ -10,6 +10,19 @@ extern "C" { #endif +/** + * @brief Perform semihosting call + * + * See ARM semihosting spec for details. + * https://static.docs.arm.com/100863/0200/semihosting.pdf + * + * @param id semihosting call number + * @param data data block to pass to the host; number of items and their + * meaning depends on the semihosting call. See the spec for + * details. + * + * @return return value from the host + */ static inline long semihosting_call_noerrno(long id, long *data) { register long a2 asm ("a2") = id; diff --git a/examples/protocols/http_server/restful_server/main/esp_rest_main.c b/examples/protocols/http_server/restful_server/main/esp_rest_main.c index f0d52ca571..5bf2e3cbe5 100644 --- a/examples/protocols/http_server/restful_server/main/esp_rest_main.c +++ b/examples/protocols/http_server/restful_server/main/esp_rest_main.c @@ -47,7 +47,7 @@ static void initialise_mdns(void) #if CONFIG_EXAMPLE_WEB_DEPLOY_SEMIHOST esp_err_t init_fs(void) { - esp_err_t ret = esp_vfs_semihost_register(CONFIG_EXAMPLE_WEB_MOUNT_POINT, CONFIG_EXAMPLE_HOST_PATH_TO_MOUNT); + esp_err_t ret = esp_vfs_semihost_register(CONFIG_EXAMPLE_WEB_MOUNT_POINT); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to register semihost driver (%s)!", esp_err_to_name(ret)); return ESP_FAIL; diff --git a/examples/storage/semihost_vfs/README.md b/examples/storage/semihost_vfs/README.md index c5c1e2e750..696b9460ab 100644 --- a/examples/storage/semihost_vfs/README.md +++ b/examples/storage/semihost_vfs/README.md @@ -54,7 +54,7 @@ This example also requires [OpenOCD](https://docs.espressif.com/projects/esp-idf ### Overriding the base directory for semihosting -When the example application calls `esp_vfs_semihost_register("/host", NULL)`, the path `/host` on the ESP target is mapped to the semihosting _base directory_. By default, this is the directory where OpenOCD program is started from. In the instructions above, OpenOCD is started in `data` subdirectory of the example project. +When the example application calls `esp_vfs_semihost_register("/host")`, the path `/host` on the ESP target is mapped to the semihosting _base directory_. By default, this is the directory where OpenOCD program is started from. In the instructions above, OpenOCD is started in `data` subdirectory of the example project. When debugging with Xtensa based SoCs (ESP32, ESP32-S2, ESP32-S3) it is possible to override the semihosting base directory using an additional flag of `openocd` command. For example, on Linux and macOS: diff --git a/examples/storage/semihost_vfs/main/semihost_vfs_example_main.c b/examples/storage/semihost_vfs/main/semihost_vfs_example_main.c index b8bba77208..3db7d566b0 100644 --- a/examples/storage/semihost_vfs/main/semihost_vfs_example_main.c +++ b/examples/storage/semihost_vfs/main/semihost_vfs_example_main.c @@ -26,7 +26,7 @@ static uint8_t s_buf[512]; void app_main(void) { // Register host FS at '/host'. On the host file will be written/read in the current semihosting dir of OpenOCD - esp_err_t ret = esp_vfs_semihost_register("/host", NULL); + esp_err_t ret = esp_vfs_semihost_register("/host"); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to register semihost driver (%s)!", esp_err_to_name(ret)); return;