aboutsummaryrefslogtreecommitdiff
path: root/src/target
diff options
context:
space:
mode:
authorErhan Kurubas <erhan.kurubas@espressif.com>2022-04-05 14:26:08 +0300
committerAntonio Borneo <borneo.antonio@gmail.com>2022-06-24 21:47:43 +0000
commit334a187e64121cb1f8bf6f07f5400e0e5ba8c0ff (patch)
tree3792c18bd6f673b270e4d2a8bf5609b01a47978a /src/target
parentaf9daf4433e006197942121a069a5e9d7ec28671 (diff)
downloadriscv-openocd-334a187e64121cb1f8bf6f07f5400e0e5ba8c0ff.zip
riscv-openocd-334a187e64121cb1f8bf6f07f5400e0e5ba8c0ff.tar.gz
riscv-openocd-334a187e64121cb1f8bf6f07f5400e0e5ba8c0ff.tar.bz2
semihosting: add custom user command handler
Custom user syscalls can be handled with target events in the TCL scripts. This patch gives another opportunity to handle custom syscalls in the c files. Besides that some utility functions are also exported for the custom handlers. Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com> Change-Id: Ice13d527540a0de0b2a8abda912ae3dcff3834b7 Reviewed-on: https://review.openocd.org/c/openocd/+/6889 Tested-by: jenkins Reviewed-by: Ian Thompson <ianst@cadence.com> Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Diffstat (limited to 'src/target')
-rw-r--r--src/target/semihosting_common.c34
-rw-r--r--src/target/semihosting_common.h18
2 files changed, 33 insertions, 19 deletions
diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c
index 0a60eb1..d54c341 100644
--- a/src/target/semihosting_common.c
+++ b/src/target/semihosting_common.c
@@ -103,16 +103,6 @@ static int semihosting_common_fileio_info(struct target *target,
static int semihosting_common_fileio_end(struct target *target, int result,
int fileio_errno, bool ctrl_c);
-static int semihosting_read_fields(struct target *target, size_t number,
- uint8_t *fields);
-static int semihosting_write_fields(struct target *target, size_t number,
- uint8_t *fields);
-static uint64_t semihosting_get_field(struct target *target, size_t index,
- uint8_t *fields);
-static void semihosting_set_field(struct target *target, uint64_t value,
- size_t index,
- uint8_t *fields);
-
/* Attempts to include gdb_server.h failed. */
extern int gdb_actual_connections;
@@ -166,6 +156,7 @@ int semihosting_common_init(struct target *target, void *setup,
semihosting->setup = setup;
semihosting->post_result = post_result;
+ semihosting->user_command_extension = NULL;
target->semihosting = semihosting;
@@ -1467,9 +1458,14 @@ int semihosting_common(struct target *target)
* Return
* On exit, the RETURN REGISTER contains the return status.
*/
- {
- assert(!semihosting_user_op_params);
+ if (semihosting->user_command_extension) {
+ retval = semihosting->user_command_extension(target);
+ if (retval != ERROR_NOT_IMPLEMENTED)
+ break;
+ /* If custom user command not handled, we are looking for the TCL handler */
+ }
+ assert(!semihosting_user_op_params);
retval = semihosting_read_fields(target, 2, fields);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to read fields for user defined command"
@@ -1507,11 +1503,8 @@ int semihosting_common(struct target *target)
target_handle_event(target, semihosting->op);
free(semihosting_user_op_params);
semihosting_user_op_params = NULL;
-
semihosting->result = 0;
break;
- }
-
case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
/*
@@ -1670,10 +1663,13 @@ static int semihosting_common_fileio_end(struct target *target, int result,
return semihosting->post_result(target);
}
+/* -------------------------------------------------------------------------
+ * Utility functions. */
+
/**
* Read all fields of a command from target to buffer.
*/
-static int semihosting_read_fields(struct target *target, size_t number,
+int semihosting_read_fields(struct target *target, size_t number,
uint8_t *fields)
{
struct semihosting *semihosting = target->semihosting;
@@ -1685,7 +1681,7 @@ static int semihosting_read_fields(struct target *target, size_t number,
/**
* Write all fields of a command from buffer to target.
*/
-static int semihosting_write_fields(struct target *target, size_t number,
+int semihosting_write_fields(struct target *target, size_t number,
uint8_t *fields)
{
struct semihosting *semihosting = target->semihosting;
@@ -1697,7 +1693,7 @@ static int semihosting_write_fields(struct target *target, size_t number,
/**
* Extract a field from the buffer, considering register size and endianness.
*/
-static uint64_t semihosting_get_field(struct target *target, size_t index,
+uint64_t semihosting_get_field(struct target *target, size_t index,
uint8_t *fields)
{
struct semihosting *semihosting = target->semihosting;
@@ -1710,7 +1706,7 @@ static uint64_t semihosting_get_field(struct target *target, size_t index,
/**
* Store a field in the buffer, considering register size and endianness.
*/
-static void semihosting_set_field(struct target *target, uint64_t value,
+void semihosting_set_field(struct target *target, uint64_t value,
size_t index,
uint8_t *fields)
{
diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h
index 404080f..1b71690 100644
--- a/src/target/semihosting_common.h
+++ b/src/target/semihosting_common.h
@@ -179,6 +179,13 @@ struct semihosting {
/** Base directory for semihosting I/O operations. */
char *basedir;
+ /**
+ * Target's extension of semihosting user commands.
+ * @returns ERROR_NOT_IMPLEMENTED when user command is not handled, otherwise
+ * sets semihosting->result and semihosting->sys_errno and returns ERROR_OK.
+ */
+ int (*user_command_extension)(struct target *target);
+
int (*setup)(struct target *target, int enable);
int (*post_result)(struct target *target);
};
@@ -187,4 +194,15 @@ int semihosting_common_init(struct target *target, void *setup,
void *post_result);
int semihosting_common(struct target *target);
+/* utility functions which may also be used by semihosting extensions (custom vendor-defined syscalls) */
+int semihosting_read_fields(struct target *target, size_t number,
+ uint8_t *fields);
+int semihosting_write_fields(struct target *target, size_t number,
+ uint8_t *fields);
+uint64_t semihosting_get_field(struct target *target, size_t index,
+ uint8_t *fields);
+void semihosting_set_field(struct target *target, uint64_t value,
+ size_t index,
+ uint8_t *fields);
+
#endif /* OPENOCD_TARGET_SEMIHOSTING_COMMON_H */