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:
parent
af9daf4433
commit
334a187e64
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue