rtos: Add support for Zephyr RTOS
[fw/openocd] / src / rtos / rtos.c
index cd2e271f68beea23b37c445f29a1beede3e53a64..fdb3862d8ba74c241ce87ee38be5226466e0650d 100644 (file)
@@ -31,27 +31,36 @@ extern struct rtos_type FreeRTOS_rtos;
 extern struct rtos_type ThreadX_rtos;
 extern struct rtos_type eCos_rtos;
 extern struct rtos_type Linux_os;
-extern struct rtos_type ChibiOS_rtos;
+extern struct rtos_type chibios_rtos;
 extern struct rtos_type chromium_ec_rtos;
 extern struct rtos_type embKernel_rtos;
 extern struct rtos_type mqx_rtos;
 extern struct rtos_type uCOS_III_rtos;
 extern struct rtos_type nuttx_rtos;
+extern struct rtos_type hwthread_rtos;
+extern struct rtos_type riot_rtos;
+extern struct rtos_type zephyr_rtos;
 
 static struct rtos_type *rtos_types[] = {
        &ThreadX_rtos,
        &FreeRTOS_rtos,
        &eCos_rtos,
        &Linux_os,
-       &ChibiOS_rtos,
+       &chibios_rtos,
        &chromium_ec_rtos,
        &embKernel_rtos,
        &mqx_rtos,
        &uCOS_III_rtos,
        &nuttx_rtos,
+       &riot_rtos,
+       &zephyr_rtos,
+       /* keep this as last, as it always matches with rtos auto */
+       &hwthread_rtos,
        NULL
 };
 
+static int rtos_try_next(struct target *target);
+
 int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
 
 int rtos_smp_init(struct target *target)
@@ -95,9 +104,7 @@ static void os_free(struct target *target)
        if (!target->rtos)
                return;
 
-       if (target->rtos->symbols)
-               free(target->rtos->symbols);
-
+       free(target->rtos->symbols);
        free(target->rtos);
        target->rtos = NULL;
 }
@@ -119,7 +126,7 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target)
 {
        int x;
        const char *cp;
-       struct Jim_Obj *res;
+       Jim_Obj *res;
        int e;
 
        if (!goi->isconfigure && goi->argc != 0) {
@@ -157,6 +164,11 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target)
        return JIM_ERR;
 }
 
+void rtos_destroy(struct target *target)
+{
+       os_free(target);
+}
+
 int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size)
 {
        struct target *target = get_target_from_connection(connection);
@@ -166,9 +178,9 @@ int gdb_thread_packet(struct connection *connection, char const *packet, int pac
        return target->rtos->gdb_thread_packet(connection, packet, packet_size);
 }
 
-static symbol_table_elem_t *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr)
+static struct symbol_table_elem *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr)
 {
-       symbol_table_elem_t *s;
+       struct symbol_table_elem *s;
 
        if (!os->symbols)
                os->type->get_symbol_list_to_lookup(&os->symbols);
@@ -190,7 +202,7 @@ static symbol_table_elem_t *next_symbol(struct rtos *os, char *cur_symbol, uint6
  * if 'symbol' is not declared optional */
 static bool is_symbol_mandatory(const struct rtos *os, const char *symbol)
 {
-       for (symbol_table_elem_t *s = os->symbols; s->symbol_name; ++s) {
+       for (struct symbol_table_elem *s = os->symbols; s->symbol_name; ++s) {
                if (!strcmp(s->symbol_name, symbol))
                        return !s->optional;
        }
@@ -221,8 +233,8 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s
        int rtos_detected = 0;
        uint64_t addr = 0;
        size_t reply_len;
-       char reply[GDB_BUFFER_SIZE], cur_sym[GDB_BUFFER_SIZE / 2] = "";
-       symbol_table_elem_t *next_sym = NULL;
+       char reply[GDB_BUFFER_SIZE + 1], cur_sym[GDB_BUFFER_SIZE / 2 + 1] = ""; /* Extra byte for null-termination */
+       struct symbol_table_elem *next_sym = NULL;
        struct target *target = get_target_from_connection(connection);
        struct rtos *os = target->rtos;
 
@@ -460,6 +472,7 @@ static int rtos_put_gdb_reg_list(struct connection *connection,
        return ERROR_OK;
 }
 
+/** Look through all registers to find this register. */
 int rtos_get_gdb_reg(struct connection *connection, int reg_num)
 {
        struct target *target = get_target_from_connection(connection);
@@ -471,19 +484,31 @@ int rtos_get_gdb_reg(struct connection *connection, int reg_num)
                struct rtos_reg *reg_list;
                int num_regs;
 
-               LOG_DEBUG("RTOS: getting register %d for thread 0x%" PRIx64
-                                 ", target->rtos->current_thread=0x%" PRIx64 "\r\n",
+               LOG_DEBUG("getting register %d for thread 0x%" PRIx64
+                                 ", target->rtos->current_thread=0x%" PRIx64,
                                                                                reg_num,
                                                                                current_threadid,
                                                                                target->rtos->current_thread);
 
-               int retval = target->rtos->type->get_thread_reg_list(target->rtos,
-                               current_threadid,
-                               &reg_list,
-                               &num_regs);
-               if (retval != ERROR_OK) {
-                       LOG_ERROR("RTOS: failed to get register list");
-                       return retval;
+               int retval;
+               if (target->rtos->type->get_thread_reg) {
+                       reg_list = calloc(1, sizeof(*reg_list));
+                       num_regs = 1;
+                       retval = target->rtos->type->get_thread_reg(target->rtos,
+                                       current_threadid, reg_num, &reg_list[0]);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("RTOS: failed to get register %d", reg_num);
+                               return retval;
+                       }
+               } else {
+                       retval = target->rtos->type->get_thread_reg_list(target->rtos,
+                                       current_threadid,
+                                       &reg_list,
+                                       &num_regs);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("RTOS: failed to get register list");
+                               return retval;
+                       }
                }
 
                for (int i = 0; i < num_regs; ++i) {
@@ -499,6 +524,7 @@ int rtos_get_gdb_reg(struct connection *connection, int reg_num)
        return ERROR_FAIL;
 }
 
+/** Return a list of general registers. */
 int rtos_get_gdb_reg_list(struct connection *connection)
 {
        struct target *target = get_target_from_connection(connection);
@@ -532,6 +558,20 @@ int rtos_get_gdb_reg_list(struct connection *connection)
        return ERROR_FAIL;
 }
 
+int rtos_set_reg(struct connection *connection, int reg_num,
+               uint8_t *reg_value)
+{
+       struct target *target = get_target_from_connection(connection);
+       int64_t current_threadid = target->rtos->current_threadid;
+       if ((target->rtos != NULL) &&
+                       (target->rtos->type->set_reg != NULL) &&
+                       (current_threadid != -1) &&
+                       (current_threadid != 0)) {
+               return target->rtos->type->set_reg(target->rtos, reg_num, reg_value);
+       }
+       return ERROR_FAIL;
+}
+
 int rtos_generic_stack_read(struct target *target,
        const struct rtos_register_stacking *stacking,
        int64_t stack_ptr,
@@ -593,7 +633,7 @@ int rtos_generic_stack_read(struct target *target,
        return ERROR_OK;
 }
 
-int rtos_try_next(struct target *target)
+static int rtos_try_next(struct target *target)
 {
        struct rtos *os = target->rtos;
        struct rtos_type **type = rtos_types;
@@ -608,10 +648,9 @@ int rtos_try_next(struct target *target)
                return 0;
 
        os->type = *type;
-       if (os->symbols) {
-               free(os->symbols);
-               os->symbols = NULL;
-       }
+
+       free(os->symbols);
+       os->symbols = NULL;
 
        return 1;
 }