This is an automated email from Gerrit.

Armin van der Togt ([email protected]) just uploaded a new patch set to Gerrit, 
which you can find at http://openocd.zylin.com/4038

-- gerrit

commit 1f220ac39c01a8cf7e9c32a20ca002aae78f18a5
Author: Armin van der Togt <[email protected]>
Date:   Thu Mar 2 20:21:45 2017 +0100

    rtos: Add support for µOS++IIIe
    
    µOS++IIIe is an open-source rtos written in C++ by Liviu Ionescu. This 
patch adds support to openocd for it.
    µOS++IIIe can be found here: http://micro-os-plus.github.io/
    
    Change-Id: I873ef98cb0a61bdcbb2013d4c7af7930f1f42638
    Signed-off-by: Armin van der Togt <[email protected]>

diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am
index c59ee3f..2c15f8e 100644
--- a/src/rtos/Makefile.am
+++ b/src/rtos/Makefile.am
@@ -15,6 +15,7 @@ noinst_LTLIBRARIES += %D%/librtos.la
        %D%/embKernel.c \
        %D%/mqx.c \
        %D%/uCOS-III.c \
+       %D%/microOSplusIIIe.c \
        %D%/rtos.h \
        %D%/rtos_standard_stackings.h \
        %D%/rtos_ecos_stackings.h \
diff --git a/src/rtos/microOSplusIIIe.c b/src/rtos/microOSplusIIIe.c
new file mode 100644
index 0000000..12aba2f
--- /dev/null
+++ b/src/rtos/microOSplusIIIe.c
@@ -0,0 +1,392 @@
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/time_support.h>
+#include <jtag/jtag.h>
+#include "target/target.h"
+#include "target/target_type.h"
+#include "rtos.h"
+#include "helper/log.h"
+#include "helper/types.h"
+#include "rtos_standard_stackings.h"
+#include "target/armv7m.h"
+#include "target/cortex_m.h"
+
+static int microOSplusIIIe_detect_rtos(struct target *target);
+static int microOSplusIIIe_create(struct target *target);
+static int microOSplusIIIe_update_threads(struct rtos *rtos);
+static int microOSplusIIIe_get_thread_reg_list(struct rtos *rtos, int64_t 
thread_id, char **hex_reg_list);
+static int microOSplusIIIe_get_symbol_list_to_lookup(symbol_table_elem_t 
*symbol_list[]);
+
+struct microOSplusIIIe_thread_state {
+       int value;
+       const char *desc;
+};
+
+#define MICROOSPLUSIIIE_THREAD_NAME_STR_SIZE (200)
+
+static const struct microOSplusIIIe_thread_state 
microOSplusIIIe_thread_states[] = { { 0, "Undefined" }, { 1, "Ready" },
+               { 2, "Running" }, { 3, "Suspended" }, { 4, "Terminated" }, { 5, 
"Destroyed" }, };
+
+#define MICROOSPLUSIIIE_NUM_STATES 
(sizeof(microOSplusIIIe_thread_states)/sizeof(struct 
microOSplusIIIe_thread_state))
+
+struct microOSplusIIIe_params {
+       const char *target_name;
+       unsigned char pointer_width;
+       unsigned char thread_name_offset;
+       unsigned char thread_parent_offset;
+       unsigned char thread_list_node_offset;
+       unsigned char thread_children_node_offset;
+       unsigned char thread_state_offset;
+       unsigned char thread_stack_bottom_offset;
+       unsigned char thread_stack_offset;
+       const struct rtos_register_stacking *stacking_info_default;
+       const struct rtos_register_stacking *stacking_info_with_fpu;
+};
+
+static const struct microOSplusIIIe_params microOSplusIIIe_params_list[] = { { 
"cortex_m", /* target_name */
+4, /* pointer_width; */
+0x04, /* thread_name_offset; */
+0x24, /* thread_parent_offset; */
+0x28, /* thread_list_node_offset; */
+0x30, /* thread_children_node_offset; */
+0x60, /* thread_state_offset; */
+0x70, /* thread_stack_bottom_offset; */
+0x80, /* thread_stack_offset; */
+&rtos_standard_Cortex_M4F_stacking, /* stacking_info */
+&rtos_standard_Cortex_M4F_FPU_stacking, /* stacking_info */
+}, { "hla_target", /* target_name */
+4, /* pointer_width; */
+0x04, /* thread_name_offset; */
+0x24, /* thread_parent_offset; */
+0x28, /* thread_list_node_offset; */
+0x30, /* thread_children_node_offset; */
+0x60, /* thread_state_offset; */
+0x70, /* thread_stack_bottom_offset; */
+0x80, /* thread_stack_offset; */
+&rtos_standard_Cortex_M4F_stacking, /* stacking_info */
+&rtos_standard_Cortex_M4F_FPU_stacking, /* stacking_info */
+}, };
+
+#define MICROOSPLUSIIIE_NUM_PARAMS 
((int)(sizeof(microOSplusIIIe_params_list)/sizeof(struct 
microOSplusIIIe_params)))
+
+enum microOSplusIIIe_symbol_values {
+       microOSplusIIIe_VAL_thread_list = 0,
+       microOSplusIIIe_VAL_current_thread_ptr = 1,
+       microOSplusIIIe_VAL_scheduler_is_started = 2,
+};
+
+static const char * const microOSplusIIIe_symbol_list[] = { 
"os::rtos::scheduler::top_threads_list_",
+               "os::rtos::scheduler::current_thread_", 
"os::rtos::scheduler::is_started_",
+               NULL };
+
+const struct rtos_type microOSplusIIIe_rtos = { .name = "µOS++ IIIe",
+
+.detect_rtos = microOSplusIIIe_detect_rtos, .create = microOSplusIIIe_create, 
.update_threads =
+               microOSplusIIIe_update_threads, .get_thread_reg_list = 
microOSplusIIIe_get_thread_reg_list,
+               .get_symbol_list_to_lookup = 
microOSplusIIIe_get_symbol_list_to_lookup,
+
+};
+
+static int microOSplusIIIe_get_thread_info(struct rtos *rtos, uint32_t 
thread_index,
+               struct thread_detail *thread_details)
+{
+       const struct microOSplusIIIe_params *param = (const struct 
microOSplusIIIe_params *) rtos->rtos_specific_params;
+       char tmp_str[MICROOSPLUSIIIE_THREAD_NAME_STR_SIZE];
+       int retval;
+       /* Thread id is thread address */
+       thread_details->threadid = thread_index;
+       uint32_t name_ptr = 0;
+       /* read the name pointer */
+       retval = target_read_buffer(rtos->target, thread_index + 
param->thread_name_offset, param->pointer_width,
+                       (uint8_t *) &name_ptr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Could not read µOS++ IIIe thread name pointer from 
target");
+               return retval;
+       }
+
+       /* Read the thread name */
+       retval = target_read_buffer(rtos->target, name_ptr,
+       MICROOSPLUSIIIE_THREAD_NAME_STR_SIZE, (uint8_t *) &tmp_str);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error reading thread name from µOS++ IIIe target");
+               return retval;
+       }
+       tmp_str[MICROOSPLUSIIIE_THREAD_NAME_STR_SIZE - 1] = '\x00';
+
+       if (tmp_str[0] == '\x00')
+               strcpy(tmp_str, "No Name");
+
+       thread_details->thread_name_str = malloc(strlen(tmp_str) + 1);
+       strcpy(thread_details->thread_name_str, tmp_str);
+
+       /* Read the thread status */
+       uint8_t thread_status = 0;
+       retval = target_read_buffer(rtos->target, thread_index + 
param->thread_state_offset, 1, &thread_status);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error reading thread state from µOS++ IIIe target");
+               return retval;
+       }
+       /* Read the parent id */
+       uint32_t thread_parent;
+       retval = target_read_buffer(rtos->target, thread_index + 
param->thread_parent_offset, param->pointer_width,
+                       (uint8_t *) &thread_parent);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error reading parent id from µOS++ IIIe target");
+               return retval;
+       }
+
+       if (thread_status >= MICROOSPLUSIIIE_NUM_STATES)
+               thread_status = 0;
+       const char *state_desc;
+       state_desc = microOSplusIIIe_thread_states[thread_status].desc;
+
+       thread_details->extra_info_str = malloc(strlen(state_desc) + 30);
+       sprintf(thread_details->extra_info_str, "State: %s, parent: %u", 
state_desc, thread_parent);
+
+       thread_details->exists = true;
+       return 0;
+
+}
+
+static int microOSplusIIIe_get_thread_info_recursive(struct rtos *rtos, 
uint32_t list_head, uint32_t list_prev,
+               int *thread_list_index,
+               bool count_only)
+{
+       const struct microOSplusIIIe_params *param = (const struct 
microOSplusIIIe_params *) rtos->rtos_specific_params;
+       int retval = 0;
+       if (list_prev == list_head)
+               return retval;
+       if (!count_only) {
+               microOSplusIIIe_get_thread_info(rtos, list_prev - 
param->thread_list_node_offset,
+                               &(rtos->thread_details[*thread_list_index]));
+       }
+       (*thread_list_index)++;
+       uint32_t children_head = list_prev - param->thread_list_node_offset + 
param->thread_children_node_offset;
+       uint32_t children_prev;
+       retval = target_read_buffer(rtos->target, children_head, 
param->pointer_width, (uint8_t *) &children_prev);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = microOSplusIIIe_get_thread_info_recursive(rtos, children_head, 
children_prev, thread_list_index,
+                       count_only);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = target_read_buffer(rtos->target, list_prev, 
param->pointer_width, (uint8_t *) &list_prev);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = microOSplusIIIe_get_thread_info_recursive(rtos, list_head, 
list_prev, thread_list_index, count_only);
+       return retval;
+}
+
+static int microOSplusIIIe_create_single_thread(struct rtos *rtos)
+{
+       /* No RTOS threads - there is always at least the current execution 
though */
+       char tmp_str[] = "Current Execution";
+       rtos->thread_details = malloc(sizeof(struct thread_detail));
+       if (!rtos->thread_details) {
+               LOG_ERROR("Error allocating memory for 1 thread");
+               return ERROR_FAIL;
+       }
+       rtos->thread_details->threadid = 1;
+       rtos->thread_details->exists = true;
+       rtos->thread_details->extra_info_str = NULL;
+       rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
+       strcpy(rtos->thread_details->thread_name_str, tmp_str);
+       rtos->thread_count = 1;
+       rtos->current_thread = 1;
+       return ERROR_OK;
+}
+
+static int microOSplusIIIe_update_threads(struct rtos *rtos)
+{
+       int retval;
+       int thread_count = 0;
+       const struct microOSplusIIIe_params *param;
+
+       if (rtos == NULL)
+               return -1;
+
+       if (rtos->rtos_specific_params == NULL)
+               return -3;
+
+       param = (const struct microOSplusIIIe_params *) 
rtos->rtos_specific_params;
+
+       if (rtos->symbols == NULL) {
+               LOG_ERROR("No symbols for µOS++ IIIe");
+               return -4;
+       }
+
+       if (rtos->symbols[microOSplusIIIe_VAL_thread_list].address == 0) {
+               LOG_ERROR("Don't have the thread list head");
+               return -2;
+       }
+
+       /* wipe out previous thread details if any */
+       rtos_free_threadlist(rtos);
+
+       /* read os::rtos::scheduler::is_started_ to see if the scheduler has 
been started */
+       uint8_t is_started;
+       retval = target_read_buffer(rtos->target, 
rtos->symbols[microOSplusIIIe_VAL_scheduler_is_started].address, 1,
+                       (uint8_t *) &is_started);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (is_started == 0) {
+               /* scheduler not yet started, return single thread */
+               return microOSplusIIIe_create_single_thread(rtos);
+       }
+       /* read the top_thread list head  */
+       uint32_t thread_list_head = 
rtos->symbols[microOSplusIIIe_VAL_thread_list].address;
+       uint32_t first_thread;
+       retval = target_read_buffer(rtos->target, thread_list_head, 
param->pointer_width, (uint8_t *) &first_thread);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (first_thread == 0 || first_thread == thread_list_head) {
+               /* this should only be possible during initialization */
+               return microOSplusIIIe_create_single_thread(rtos);
+       } else {
+               /* calculate the number of threads */
+               retval = microOSplusIIIe_get_thread_info_recursive(rtos, 
thread_list_head, first_thread, &thread_count, true);
+               if (retval != 0)
+                       return retval;
+               /* read the current thread id */
+               uint32_t current_thread_addr;
+               retval = target_read_buffer(rtos->target, 
rtos->symbols[microOSplusIIIe_VAL_current_thread_ptr].address, 4,
+                               (uint8_t *) &current_thread_addr);
+               if (retval != ERROR_OK)
+                       return retval;
+               if (thread_count == 0) {
+                       /* this should never happen */
+                       LOG_ERROR("Thread list is empty!");
+                       return microOSplusIIIe_create_single_thread(rtos);
+               }
+               rtos->thread_count = thread_count;
+               /* Use thread address as thread id */
+               rtos->current_thread = current_thread_addr;
+               /* create space for new thread details */
+               rtos->thread_details = malloc(sizeof(struct thread_detail) * 
thread_count);
+               int thread_list_index = 0;
+               /* read information about the available threads */
+               microOSplusIIIe_get_thread_info_recursive(rtos, 
thread_list_head, first_thread, &thread_list_index, false);
+       }
+       return 0;
+}
+
+static int microOSplusIIIe_get_thread_reg_list(struct rtos *rtos, int64_t 
thread_id, char **hex_reg_list)
+{
+       int retval;
+       const struct microOSplusIIIe_params *param;
+
+       *hex_reg_list = NULL;
+
+       if (rtos == NULL)
+               return -1;
+
+       if (thread_id == 0)
+               return -2;
+
+       if (rtos->rtos_specific_params == NULL)
+               return -3;
+
+       param = (const struct microOSplusIIIe_params *) 
rtos->rtos_specific_params;
+
+       /* Read the stack pointer */
+       int64_t stack_ptr = 0;
+       retval = target_read_buffer(rtos->target, thread_id + 
param->thread_stack_offset, param->pointer_width,
+                       (uint8_t *) &stack_ptr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error reading stack frame from µOS++ IIIe thread");
+               return retval;
+       }
+
+       bool fpu_enabled = false;
+       struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);
+       if (is_armv7m(armv7m_target)) {
+               if (armv7m_target->fp_feature == FPv4_SP) {
+                       /* Found ARM v7m target which includes a FPU */
+                       uint32_t cpacr;
+
+                       retval = target_read_u32(rtos->target, FPU_CPACR, 
&cpacr);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("Could not read CPACR register to 
check FPU state");
+                               return -1;
+                       }
+
+                       /* Check if CP10 and CP11 are set to full access. */
+                       if (cpacr & 0x00F00000) {
+                               /* Found target with enabled FPU */
+                               fpu_enabled = true;
+                       }
+               }
+       }
+
+       if (fpu_enabled) {
+               /* Read the LR to decide between stacking with or without FPU */
+               uint32_t LR_svc = 0;
+               retval = target_read_buffer(rtos->target, stack_ptr + 0x20, 
param->pointer_width, (uint8_t *) &LR_svc);
+               if (retval != ERROR_OK) {
+                       LOG_OUTPUT("Error reading stack frame from FreeRTOS 
thread\r\n");
+                       return retval;
+               }
+               if ((LR_svc & 0x10) == 0)
+                       return rtos_generic_stack_read(rtos->target, 
param->stacking_info_with_fpu, stack_ptr, hex_reg_list);
+       }
+
+       return rtos_generic_stack_read(rtos->target, 
param->stacking_info_default, stack_ptr, hex_reg_list);
+}
+
+static int microOSplusIIIe_get_symbol_list_to_lookup(symbol_table_elem_t 
*symbol_list[])
+{
+       unsigned int i;
+       *symbol_list = calloc(ARRAY_SIZE(microOSplusIIIe_symbol_list), 
sizeof(symbol_table_elem_t));
+
+       for (i = 0; i < ARRAY_SIZE(microOSplusIIIe_symbol_list); i++)
+               (*symbol_list)[i].symbol_name = microOSplusIIIe_symbol_list[i];
+
+       return 0;
+}
+
+static int microOSplusIIIe_detect_rtos(struct target *target)
+{
+       if ((target->rtos->symbols != NULL) && 
(target->rtos->symbols[microOSplusIIIe_VAL_thread_list].address != 0)) {
+               /* looks like µOS++ IIIe */
+               return 1;
+       }
+       return 0;
+}
+
+static int microOSplusIIIe_create(struct target *target)
+{
+       int i = 0;
+       while ((i < MICROOSPLUSIIIE_NUM_PARAMS)
+                       && (0 != 
strcmp(microOSplusIIIe_params_list[i].target_name, target->type->name))) {
+               i++;
+       }
+       if (i >= MICROOSPLUSIIIE_NUM_PARAMS) {
+               LOG_ERROR("Could not find target in microOSplusIIIe 
compatibility list");
+               return -1;
+       }
+
+       target->rtos->rtos_specific_params = (void *) 
&microOSplusIIIe_params_list[i];
+       target->rtos->current_thread = 0;
+       target->rtos->thread_details = NULL;
+       return 0;
+}
diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
index 84ee498..10c7a95 100644
--- a/src/rtos/rtos.c
+++ b/src/rtos/rtos.c
@@ -35,6 +35,7 @@ extern struct rtos_type ChibiOS_rtos;
 extern struct rtos_type embKernel_rtos;
 extern struct rtos_type mqx_rtos;
 extern struct rtos_type uCOS_III_rtos;
+extern struct rtos_type microOSplusIIIe_rtos;
 
 static struct rtos_type *rtos_types[] = {
        &ThreadX_rtos,
@@ -45,6 +46,7 @@ static struct rtos_type *rtos_types[] = {
        &embKernel_rtos,
        &mqx_rtos,
        &uCOS_III_rtos,
+       &microOSplusIIIe_rtos,
        NULL
 };
 

-- 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to