semihosting: add custom user command handler 89/6889/6
authorErhan Kurubas <erhan.kurubas@espressif.com>
Tue, 5 Apr 2022 11:26:08 +0000 (14:26 +0300)
committerAntonio Borneo <borneo.antonio@gmail.com>
Fri, 24 Jun 2022 21:47:43 +0000 (21:47 +0000)
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>
src/target/semihosting_common.c
src/target/semihosting_common.h

index 0a60eb12118203d9a21a43445d18767c4643aeb2..d54c341ac90eff2951e56d7a34a7504eee987256 100644 (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_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;
 
 /* 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->setup = setup;
        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
                         * On exit, the RETURN REGISTER contains the return status.
                         */
                         * 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"
                        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;
                        target_handle_event(target, semihosting->op);
                        free(semihosting_user_op_params);
                        semihosting_user_op_params = NULL;
-
                        semihosting->result = 0;
                        break;
                        semihosting->result = 0;
                        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)
 {
        struct semihosting *semihosting = target->semihosting;
        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.
  */
 /**
  * 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;
        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.
  */
 /**
  * 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;
        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.
  */
 /**
  * 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)
 {
        size_t index,
        uint8_t *fields)
 {
index 404080f023401b81f0871c58900afc286c5e17f5..1b7169030200eecf29958b6e4212e0481954bdd6 100644 (file)
@@ -179,6 +179,13 @@ struct semihosting {
        /** Base directory for semihosting I/O operations. */
        char *basedir;
 
        /** 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);
 };
        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);
 
        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 */
 #endif /* OPENOCD_TARGET_SEMIHOSTING_COMMON_H */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)