OpenOCD
esp_semihosting.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Semihosting API for Espressif chips *
5  * Copyright (C) 2022 Espressif Systems Ltd. *
6  ***************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 
12 #include <helper/log.h>
13 #include <target/target.h>
15 #include "esp_semihosting.h"
16 #include "esp_xtensa.h"
17 
18 static struct esp_semihost_data __attribute__((unused)) *target_to_esp_semihost_data(struct target *target)
19 {
20  struct xtensa *xtensa = target->arch_info;
23  /* TODO: add riscv */
24  LOG_ERROR("Unknown target arch!");
25  return NULL;
26 }
27 
28 static int esp_semihosting_sys_seek(struct target *target, uint64_t fd, uint32_t pos, size_t whence)
29 {
31 
32  semihosting->result = lseek(fd, pos, whence);
33  semihosting->sys_errno = errno;
34  LOG_TARGET_DEBUG(target, "lseek(%" PRIx64 ", %" PRIu32 " %" PRId64 ")=%d", fd, pos, semihosting->result, errno);
35  return ERROR_OK;
36 }
37 
39 {
41  if (!semihosting)
42  /* Silently ignore if the semihosting field was not set. */
43  return ERROR_OK;
44 
45  int retval = ERROR_NOT_IMPLEMENTED;
46 
47  /* Enough space to hold 4 long words. */
48  uint8_t fields[4 * 8];
49 
50  /*
51  * By default return an error.
52  * The actual result must be set by each function
53  */
54  semihosting->result = -1;
55  semihosting->sys_errno = EIO;
56 
57  LOG_TARGET_DEBUG(target, "op=0x%x, param=0x%" PRIx64, semihosting->op, semihosting->param);
58 
59  switch (semihosting->op) {
61  /* Return success to make esp-idf application happy */
62  retval = ERROR_OK;
63  semihosting->result = 0;
65  break;
66 
68  retval = semihosting_read_fields(target, 3, fields);
69  if (retval == ERROR_OK) {
70  uint64_t fd = semihosting_get_field(target, 0, fields);
71  uint32_t pos = semihosting_get_field(target, 1, fields);
72  size_t whence = semihosting_get_field(target, 2, fields);
73  retval = esp_semihosting_sys_seek(target, fd, pos, whence);
74  }
75  break;
76 
81  /* For the time being only riscv chips support these commands
82  * TODO: invoke riscv custom command handler */
83  break;
84  }
85 
86  return retval;
87 }
88 
90 {
92 
93  if (!target) {
94  LOG_ERROR("No target selected");
95  return ERROR_FAIL;
96  }
97 
99  if (!semihosting) {
100  command_print(CMD, "semihosting not supported for current target");
101  return ERROR_FAIL;
102  }
103 
104  if (!semihosting->is_active) {
105  if (semihosting->setup(target, true) != ERROR_OK) {
106  LOG_ERROR("Failed to Configure semihosting");
107  return ERROR_FAIL;
108  }
109  semihosting->is_active = true;
110  }
111 
112  if (CMD_ARGC > 0) {
113  free(semihosting->basedir);
114  semihosting->basedir = strdup(CMD_ARGV[0]);
115  if (!semihosting->basedir) {
116  command_print(CMD, "semihosting failed to allocate memory for basedir!");
117  return ERROR_FAIL;
118  }
119  }
120 
121  command_print(CMD, "DEPRECATED! semihosting base dir: %s",
123 
124  return ERROR_OK;
125 }
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:443
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:141
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define CMD_CTX
Use this macro to access the context of the command being handled, rather than accessing the variable...
Definition: command.h:146
int esp_semihosting_basedir_command(struct command_invocation *cmd)
static struct esp_semihost_data __attribute__((unused))
int esp_semihosting_common(struct target *target)
static int esp_semihosting_sys_seek(struct target *target, uint64_t fd, uint32_t pos, size_t whence)
#define ESP_SEMIHOSTING_SYS_WATCHPOINT_SET
#define ESP_SEMIHOSTING_SYS_DEBUG_STUBS_INIT
#define ESP_SEMIHOSTING_SYS_APPTRACE_INIT
#define ESP_SEMIHOSTING_SYS_DRV_INFO
#define ESP_SEMIHOSTING_SYS_BREAKPOINT_SET
#define ESP_SEMIHOSTING_SYS_SEEK
static struct esp_xtensa_common * target_to_esp_xtensa(struct target *target)
Definition: esp_xtensa.h:24
#define ERROR_NOT_IMPLEMENTED
Definition: log.h:174
#define ERROR_FAIL
Definition: log.h:170
#define LOG_TARGET_DEBUG(target, fmt_str,...)
Definition: log.h:149
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define ERROR_OK
Definition: log.h:164
uint64_t semihosting_get_field(struct target *target, size_t index, uint8_t *fields)
Extract a field from the buffer, considering register size and endianness.
int semihosting_read_fields(struct target *target, size_t number, uint8_t *fields)
Read all fields of a command from target to buffer.
When run_command is called, a new instance will be created on the stack, filled with the proper value...
Definition: command.h:76
struct esp_semihost_data semihost
Definition: esp_xtensa.h:20
int(* setup)(struct target *target, int enable)
int64_t result
The current semihosting result to be returned to the application.
char * basedir
Base directory for semihosting I/O operations.
bool is_active
A flag reporting whether semihosting is active.
int op
The current semihosting operation (R0 on ARM).
int sys_errno
The value to be returned by semihosting SYS_ERRNO request.
uint64_t param
The current semihosting parameter (R1 or ARM).
Definition: target.h:116
struct semihosting * semihosting
Definition: target.h:209
void * arch_info
Definition: target.h:164
Represents a generic Xtensa core.
Definition: xtensa.h:241
unsigned int common_magic
Definition: xtensa.h:242
struct target * get_current_target(struct command_context *cmd_ctx)
Definition: target.c:458
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1
#define XTENSA_COMMON_MAGIC
Definition: xtensa.h:236