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,
|
static int semihosting_common_fileio_end(struct target *target, int result,
|
||||||
int fileio_errno, bool ctrl_c);
|
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. */
|
/* Attempts to include gdb_server.h failed. */
|
||||||
extern int gdb_actual_connections;
|
extern int gdb_actual_connections;
|
||||||
|
|
||||||
|
@ -166,6 +156,7 @@ int semihosting_common_init(struct target *target, void *setup,
|
||||||
|
|
||||||
semihosting->setup = setup;
|
semihosting->setup = setup;
|
||||||
semihosting->post_result = post_result;
|
semihosting->post_result = post_result;
|
||||||
|
semihosting->user_command_extension = NULL;
|
||||||
|
|
||||||
target->semihosting = semihosting;
|
target->semihosting = semihosting;
|
||||||
|
|
||||||
|
@ -1467,9 +1458,14 @@ int semihosting_common(struct target *target)
|
||||||
* Return
|
* Return
|
||||||
* On exit, the RETURN REGISTER contains the return status.
|
* On exit, the RETURN REGISTER contains the return status.
|
||||||
*/
|
*/
|
||||||
{
|
if (semihosting->user_command_extension) {
|
||||||
assert(!semihosting_user_op_params);
|
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);
|
retval = semihosting_read_fields(target, 2, fields);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("Failed to read fields for user defined command"
|
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);
|
target_handle_event(target, semihosting->op);
|
||||||
free(semihosting_user_op_params);
|
free(semihosting_user_op_params);
|
||||||
semihosting_user_op_params = NULL;
|
semihosting_user_op_params = NULL;
|
||||||
|
|
||||||
semihosting->result = 0;
|
semihosting->result = 0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
|
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);
|
return semihosting->post_result(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------
|
||||||
|
* Utility functions. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read all fields of a command from target to buffer.
|
* 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)
|
uint8_t *fields)
|
||||||
{
|
{
|
||||||
struct semihosting *semihosting = target->semihosting;
|
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.
|
* 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)
|
uint8_t *fields)
|
||||||
{
|
{
|
||||||
struct semihosting *semihosting = target->semihosting;
|
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.
|
* 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)
|
uint8_t *fields)
|
||||||
{
|
{
|
||||||
struct semihosting *semihosting = target->semihosting;
|
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.
|
* 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,
|
size_t index,
|
||||||
uint8_t *fields)
|
uint8_t *fields)
|
||||||
{
|
{
|
||||||
|
|
|
@ -179,6 +179,13 @@ struct semihosting {
|
||||||
/** Base directory for semihosting I/O operations. */
|
/** Base directory for semihosting I/O operations. */
|
||||||
char *basedir;
|
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 (*setup)(struct target *target, int enable);
|
||||||
int (*post_result)(struct target *target);
|
int (*post_result)(struct target *target);
|
||||||
};
|
};
|
||||||
|
@ -187,4 +194,15 @@ int semihosting_common_init(struct target *target, void *setup,
|
||||||
void *post_result);
|
void *post_result);
|
||||||
int semihosting_common(struct target *target);
|
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 */
|
#endif /* OPENOCD_TARGET_SEMIHOSTING_COMMON_H */
|
||||||
|
|
Loading…
Reference in New Issue