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>
This commit is contained in:
Erhan Kurubas 2022-04-05 14:26:08 +03:00 committed by Antonio Borneo
parent af9daf4433
commit 334a187e64
2 changed files with 33 additions and 19 deletions

View File

@ -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)
{

View File

@ -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 */