OpenOCD
esp_xtensa_semihosting.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (c) 2020 Espressif Systems (Shanghai) Co. Ltd. *
5  ***************************************************************************/
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
13 #include <target/xtensa/xtensa.h>
14 #include "esp_xtensa.h"
15 #include "esp_xtensa_semihosting.h"
16 
17 #define ESP_XTENSA_SYSCALL 0x41E0 /* XT_INS_BREAK(1, 14) */
18 #define ESP_XTENSA_SYSCALL_SZ 3
19 
20 #define XTENSA_SYSCALL_OP_REG XT_REG_IDX_A2
21 #define XTENSA_SYSCALL_RETVAL_REG XT_REG_IDX_A2
22 #define XTENSA_SYSCALL_ERRNO_REG XT_REG_IDX_A3
23 
24 static int esp_xtensa_semihosting_setup(struct target *target, int enable)
25 {
26  LOG_TARGET_DEBUG(target, "semihosting enable=%d", enable);
27 
28  return ERROR_OK;
29 }
30 
32 {
33  /* Even with the v2 and later, errno will not retrieved from A3 reg, it is safe to set */
36  return ERROR_OK;
37 }
38 
50 int esp_xtensa_semihosting(struct target *target, int *retval)
51 {
52  struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
53 
55  if ((dbg_cause & (DEBUGCAUSE_BI | DEBUGCAUSE_BN)) == 0)
56  return SEMIHOSTING_NONE;
57 
58  uint8_t brk_insn_buf[sizeof(uint32_t)] = { 0 };
60  *retval = target_read_memory(target, pc, ESP_XTENSA_SYSCALL_SZ, 1, brk_insn_buf);
61  if (*retval != ERROR_OK) {
62  LOG_TARGET_ERROR(target, "Failed to read break instruction!");
63  return SEMIHOSTING_NONE;
64  }
65 
66  uint32_t syscall_ins = buf_get_u32(brk_insn_buf, 0, 32);
67  if (syscall_ins != ESP_XTENSA_SYSCALL) {
68  *retval = ERROR_OK;
69  return SEMIHOSTING_NONE;
70  }
71 
72  if (esp_xtensa->semihost.ops && esp_xtensa->semihost.ops->prepare)
73  esp_xtensa->semihost.ops->prepare(target);
74 
77  LOG_TARGET_DEBUG(target, "Semihosting call 0x%" PRIx32 " 0x%" PRIx32 " Base dir '%s'",
78  a2,
79  a3,
81 
82  target->semihosting->op = a2;
84 
85  *retval = semihosting_common(target);
86 
87  /* Most operations are resumable, except the two exit calls. */
88  if (*retval != ERROR_OK) {
89  LOG_TARGET_ERROR(target, "Semihosting operation (op: 0x%x) error! Code: %d",
91  *retval);
92  }
93 
94  /* Resume if target it is resumable and we are not waiting on a fileio operation to complete. */
97 
98  return SEMIHOSTING_HANDLED;
99 }
100 
102 {
104 }
105 
107 {
108  int retval = xtensa_semihosting_init(target);
109  if (retval != ERROR_OK)
110  return retval;
111  target->semihosting->word_size_bytes = 4; /* 32 bits */
113  return ERROR_OK;
114 }
static uint32_t buf_get_u32(const uint8_t *_buffer, unsigned int first, unsigned int num)
Retrieves num bits from _buffer, starting at the first bit, returning the bits in a 32-bit word.
Definition: binarybuffer.h:104
int esp_semihosting_common(struct target *target)
static struct esp_xtensa_common * target_to_esp_xtensa(struct target *target)
Definition: esp_xtensa.h:24
int esp_xtensa_semihosting_init(struct target *target)
static int xtensa_semihosting_init(struct target *target)
#define ESP_XTENSA_SYSCALL_SZ
#define XTENSA_SYSCALL_RETVAL_REG
int esp_xtensa_semihosting(struct target *target, int *retval)
Checks and processes an ESP Xtensa semihosting request.
#define ESP_XTENSA_SYSCALL
static int esp_xtensa_semihosting_post_result(struct target *target)
#define XTENSA_SYSCALL_ERRNO_REG
static int esp_xtensa_semihosting_setup(struct target *target, int enable)
#define LOG_TARGET_ERROR(target, fmt_str,...)
Definition: log.h:158
#define LOG_TARGET_DEBUG(target, fmt_str,...)
Definition: log.h:149
#define ERROR_OK
Definition: log.h:164
#define a3
Definition: mips32.c:191
#define a2
Definition: mips32.c:190
int semihosting_common_init(struct target *target, void *setup, void *post_result)
Initialize common semihosting support.
int semihosting_common(struct target *target)
Portable implementation of ARM semihosting calls.
@ SEMIHOSTING_HANDLED
@ SEMIHOSTING_NONE
struct esp_semihost_ops * ops
int(* prepare)(struct target *target)
Callback called before handling semihost call.
struct esp_semihost_data semihost
Definition: esp_xtensa.h:20
bool is_resumable
Most are resumable, except the two exit calls.
bool hit_fileio
A flag reporting whether semihosting fileio operation is active.
size_t word_size_bytes
The Target (hart) word size; 8 for 64-bits targets.
int(* user_command_extension)(struct target *target)
Target's extension of semihosting user commands.
int64_t result
The current semihosting result to be returned to the application.
char * basedir
Base directory for semihosting I/O operations.
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
int target_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
Read count items of size bytes from the memory of target at the address given.
Definition: target.c:1237
void xtensa_reg_set(struct target *target, enum xtensa_reg_id reg_id, xtensa_reg_val_t value)
Definition: xtensa.c:1070
xtensa_reg_val_t xtensa_reg_get(struct target *target, enum xtensa_reg_id reg_id)
Definition: xtensa.c:1063
Holds the interface to Xtensa cores.
#define DEBUGCAUSE_BI
#define DEBUGCAUSE_BN
@ XT_REG_IDX_PC
Definition: xtensa_regs.h:16
@ XT_REG_IDX_DEBUGCAUSE
Definition: xtensa_regs.h:48
@ XT_REG_IDX_A3
Definition: xtensa_regs.h:54
@ XT_REG_IDX_A2
Definition: xtensa_regs.h:53
uint32_t xtensa_reg_val_t
Definition: xtensa_regs.h:70