This is an automated email from Gerrit.

"Andreas Fritiofson <[email protected]>" just uploaded a new patch 
set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/6668

-- gerrit

commit 2deac6554bebffc1fadc86b7d8e1ba0c212349ee
Author: Andreas Fritiofson <[email protected]>
Date:   Fri Apr 15 12:38:43 2016 +0200

    rtos: Support rt-kernel
    
    Works for the proprietary rt-kernel from rt-labs.
    
    See: https://rt-labs.com/product/rt-kernel/
    Change-Id: Id2c2e292c15fb17eab25e3d07db05014daa2a2b0
    Signed-off-by: Andreas Fritiofson <[email protected]>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 7bf0fe98b..69e2be9ff 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -4830,7 +4830,7 @@ The value should normally correspond to a static mapping 
for the
 @var{rtos_type} can be one of @option{auto}, @option{eCos},
 @option{ThreadX}, @option{FreeRTOS}, @option{linux}, @option{ChibiOS},
 @option{embKernel}, @option{mqx}, @option{uCOS-III}, @option{nuttx},
-@option{RIOT}, @option{Zephyr}
+@option{RIOT}, @option{Zephyr}, @option{rtkernel}
 @xref{gdbrtossupport,,RTOS Support}.
 
 @item @code{-defer-examine} -- skip target examination at initial JTAG chain
@@ -11124,6 +11124,7 @@ Currently supported rtos's include:
 @item @option{RIOT}
 @item @option{hwthread} (This is not an actual RTOS. 
@xref{usingopenocdsmpwithgdb,,Using OpenOCD SMP with GDB}.)
 @item @option{Zephyr}
+@item @option{rtkernel}
 @end itemize
 
 Before an RTOS can be detected, it must export certain symbols; otherwise, it 
cannot
@@ -11160,6 +11161,8 @@ _tcb_name_offset.
 @end raggedright
 @item Zephyr symbols
 _kernel, _kernel_openocd_offsets, _kernel_openocd_size_t_size
+@item rtkernel symbols
+Multiple struct offsets.
 @end table
 
 For most RTOS supported the above symbols will be exported by default. However 
for
diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am
index f09ac21a2..1dc9cb51d 100644
--- a/src/rtos/Makefile.am
+++ b/src/rtos/Makefile.am
@@ -18,6 +18,7 @@ noinst_LTLIBRARIES += %D%/librtos.la
        %D%/mqx.c \
        %D%/uCOS-III.c \
        %D%/nuttx.c \
+       %D%/rtkernel.c \
        %D%/hwthread.c \
        %D%/zephyr.c \
        %D%/riot.c \
diff --git a/src/rtos/rtkernel.c b/src/rtos/rtkernel.c
new file mode 100644
index 000000000..9855f5af0
--- /dev/null
+++ b/src/rtos/rtkernel.c
@@ -0,0 +1,397 @@
+/***************************************************************************
+ *   Copyright (C) 2016 by Andreas Fritiofson                              *
+ *   [email protected]                                          *
+ *                                                                         *
+ *   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"
+
+#define ST_DEAD     (1 << 0)    /* Task is waiting to be deleted */
+#define ST_WAIT     (1 << 1)    /* Task is blocked: */
+#define ST_SEM      (1 << 2)    /*  on semaphore */
+#define ST_MTX      (1 << 3)    /*  on mutex */
+#define ST_SIG      (1 << 4)    /*  on signal */
+#define ST_DLY      (1 << 5)    /*  on timer */
+#define ST_FLAG     (1 << 6)    /*  on flag */
+#define ST_FLAG_ALL (1 << 7)    /*  on flag and flag mode is "ALL" */
+#define ST_MBOX     (1 << 8)    /*  on mailbox */
+#define ST_STP      (1 << 9)    /*  self stopped */
+#define ST_SUSPEND  (1 << 10)   /* Task is suspended */
+#define ST_TT       (1 << 11)   /* Time triggered task */
+#define ST_TT_YIELD (1 << 12)   /* Time triggered task that yields */
+#define ST_CREATE   (1 << 13)   /* Task was created by task_create() */
+
+#define rtkernel_STRUCT(int_type, ptr_type, list_prev_offset)
+
+struct rtkernel_params {
+       const char *target_name;
+       const struct rtos_register_stacking *stacking_info_cm3;
+       const struct rtos_register_stacking *stacking_info_cm4f;
+       const struct rtos_register_stacking *stacking_info_cm4f_fpu;
+};
+
+static const struct rtkernel_params rtkernel_params_list[] = {
+       {
+       "cortex_m",                     /* target_name */
+       &rtos_standard_cortex_m3_stacking,      /* stacking_info */
+       &rtos_standard_cortex_m4f_stacking,
+       &rtos_standard_cortex_m4f_fpu_stacking,
+       },
+       {
+       "hla_target",                   /* target_name */
+       &rtos_standard_cortex_m3_stacking,      /* stacking_info */
+       &rtos_standard_cortex_m4f_stacking,
+       &rtos_standard_cortex_m4f_fpu_stacking,
+       },
+};
+
+#define RTKERNEL_NUM_PARAMS ((int)(sizeof(rtkernel_params_list)/sizeof(struct 
rtkernel_params)))
+
+static bool rtkernel_detect_rtos(struct target *target);
+static int rtkernel_create(struct target *target);
+static int rtkernel_update_threads(struct rtos *rtos);
+static int rtkernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+               struct rtos_reg **reg_list, int *num_regs);
+static int rtkernel_get_symbol_list_to_lookup(struct symbol_table_elem 
*symbol_list[]);
+
+struct rtos_type rtkernel_rtos = {
+       .name = "rtkernel",
+
+       .detect_rtos = rtkernel_detect_rtos,
+       .create = rtkernel_create,
+       .update_threads = rtkernel_update_threads,
+       .get_thread_reg_list = rtkernel_get_thread_reg_list,
+       .get_symbol_list_to_lookup = rtkernel_get_symbol_list_to_lookup,
+};
+
+enum rtkernel_symbol_values {
+       sym_os_state = 0,
+       sym___off_os_state2chain = 1,
+       sym___off_os_state2current = 2,
+       sym___off_task2chain = 3,
+       sym___off_task2magic = 4,
+       sym___off_task2stack = 5,
+       sym___off_task2state = 6,
+       sym___off_task2name = 7,
+       sym___val_task_magic = 8,
+};
+
+struct symbols {
+       const char *name;
+       bool optional;
+};
+
+static const struct symbols rtkernel_symbol_list[] = {
+       { "os_state", false },
+       { "__off_os_state2chain", false },
+       { "__off_os_state2current", false },
+       { "__off_task2chain", false },
+       { "__off_task2magic", false },
+       { "__off_task2stack", false },
+       { "__off_task2state", false },
+       { "__off_task2name", false },
+       { "__val_task_magic", false },
+       { NULL, false }
+};
+
+static int rtkernel_add_task(struct rtos *rtos, uint32_t task, uint32_t 
current_task)
+{
+       int retval;
+       int new_thread_count = rtos->thread_count + 1;
+       struct thread_detail *new_thread_details = realloc(rtos->thread_details,
+                       new_thread_count * sizeof(struct thread_detail));
+       if (new_thread_details == NULL) {
+               LOG_ERROR("Error growing memory to %d threads", 
new_thread_count);
+               return ERROR_FAIL;
+       }
+       rtos->thread_details = new_thread_details;
+       struct thread_detail *thread = &new_thread_details[rtos->thread_count];
+
+       thread->threadid = task;
+       thread->exists = true;
+
+       /* Read the task name */
+       uint32_t name;
+       retval = target_read_u32(rtos->target, task + 
rtos->symbols[sym___off_task2name].address, &name);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Could not read task name pointer from target");
+               return retval;
+       }
+       uint8_t tmp_str[32];
+       retval = target_read_buffer(rtos->target, name, sizeof(tmp_str), 
tmp_str);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error reading task name from target");
+               return retval;
+       }
+       tmp_str[sizeof(tmp_str)-1] = '\0';
+       LOG_DEBUG("task name at 0x%" PRIx32 ", value \"%s\"", name, tmp_str);
+
+       if (tmp_str[0] == '\0')
+               strcpy((char *)tmp_str, "No Name");
+
+       thread->thread_name_str = strdup((char *)tmp_str);
+
+       /* Read the task state */
+       uint16_t state;
+       retval = target_read_u16(rtos->target, task + 
rtos->symbols[sym___off_task2state].address, &state);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Could not read task state from target");
+               return retval;
+       }
+
+       LOG_DEBUG("task state 0x%" PRIx16, state);
+
+       char state_str[64] = "";
+       if (state & ST_TT)
+               strcat(state_str, "TT|");
+       if (task == current_task)
+               strcat(state_str, "RUN");
+       else {
+               if (state == ST_TT)
+                       strcat(state_str, "READY");
+               if (state & ST_DEAD)
+                       strcat(state_str, "DEAD");
+               else if (state & ST_WAIT)
+                       strcat(state_str, "WAIT");
+               else if (state & ST_SUSPEND)
+                       strcat(state_str, "SUSP");
+               else
+                       strcat(state_str, "READY");
+       }
+       if (state & ST_SEM)
+               strcat(state_str, "|SEM");
+       if (state & ST_MTX)
+               strcat(state_str, "|MTX");
+       if (state & ST_SIG)
+               strcat(state_str, "|SIG");
+       if (state & ST_DLY)
+               strcat(state_str, "|DLY");
+       if ((state & ST_FLAG) || (state & ST_FLAG_ALL))
+               strcat(state_str, "|FLAG");
+       if (state & ST_FLAG_ALL)
+               strcat(state_str, "_ALL");
+       if (state & ST_MBOX)
+               strcat(state_str, "|MBOX");
+       if (state & ST_STP)
+               strcat(state_str, "|STP");
+
+       thread->extra_info_str = strdup(state_str);
+
+       rtos->thread_count = new_thread_count;
+       if (task == current_task)
+               rtos->current_thread = task;
+       return ERROR_OK;
+}
+
+static int rtkernel_verify_task(struct rtos *rtos, uint32_t task)
+{
+       int retval;
+       uint32_t magic;
+       retval = target_read_u32(rtos->target, task + 
rtos->symbols[sym___off_task2magic].address, &magic);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Could not read task magic from target");
+               return retval;
+       }
+       if (magic != rtos->symbols[sym___val_task_magic].address) {
+               LOG_ERROR("Invalid task found (magic=0x%"PRIx32")", magic);
+               return ERROR_FAIL;
+       }
+       return retval;
+}
+
+static int rtkernel_update_threads(struct rtos *rtos)
+{
+       int retval;
+
+       /* wipe out previous thread details if any */
+       /* do this first because rtos layer does not check our retval */
+       rtos_free_threadlist(rtos);
+       rtos->current_thread = 0;
+
+       if (rtos->symbols == NULL) {
+               LOG_ERROR("No symbols for rt-kernel");
+               return -3;
+       }
+
+       /* read the current task */
+       uint32_t current_task;
+       retval = target_read_u32(rtos->target,
+                       rtos->symbols[sym_os_state].address + 
rtos->symbols[sym___off_os_state2current].address,
+                       &current_task);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error reading current task");
+               return retval;
+       }
+       LOG_DEBUG("current task is 0x%"PRIx32, current_task);
+
+       retval = rtkernel_verify_task(rtos, current_task);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Current task is invalid");
+               return retval;
+       }
+
+       /* loop through kernel task list */
+       uint32_t chain = rtos->symbols[sym_os_state].address + 
rtos->symbols[sym___off_os_state2chain].address;
+       LOG_DEBUG("chain start at 0x%"PRIx32, chain);
+
+       uint32_t next = chain;
+       for (;;) {
+               retval = target_read_u32(rtos->target, next, &next);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Could not read rt-kernel data structure from 
target");
+                       return retval;
+               }
+               LOG_DEBUG("next entry at 0x%" PRIx32, next);
+               if (next == chain) {
+                       LOG_DEBUG("end of chain detected");
+                       break;
+               }
+               uint32_t task = next - 
rtos->symbols[sym___off_task2chain].address;
+               LOG_DEBUG("found task at 0x%" PRIx32, task);
+
+               retval = rtkernel_verify_task(rtos, task);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Invalid task found");
+                       return retval;
+               }
+
+               retval = rtkernel_add_task(rtos, task, current_task);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Could not add task to rtos system");
+                       return retval;
+               }
+       }
+       return 0;
+}
+
+static int rtkernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+               struct rtos_reg **reg_list, int *num_regs)
+{
+       int retval;
+       const struct rtkernel_params *param;
+       uint32_t stack_ptr = 0;
+
+       if (rtos == NULL)
+               return -1;
+
+       if (thread_id == 0)
+               return -2;
+
+       if (rtos->rtos_specific_params == NULL)
+               return -1;
+
+       param = (const struct rtkernel_params *) rtos->rtos_specific_params;
+
+       /* Read the stack pointer */
+       retval = target_read_u32(rtos->target, thread_id + 
rtos->symbols[sym___off_task2stack].address, &stack_ptr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error reading stack pointer from rtkernel thread");
+               return retval;
+       }
+       LOG_DEBUG("stack pointer at 0x%" PRIx64 ", value 0x%" PRIx32,
+                       thread_id + rtos->symbols[sym___off_task2stack].address,
+                       stack_ptr);
+
+       /* Adjust stack pointer to ignore non-standard BASEPRI register 
stacking */
+       stack_ptr += 4;
+
+       /* Check for armv7m with *enabled* FPU, i.e. a Cortex M4F */
+       int cm4_fpu_enabled = 0;
+       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 */
+                               cm4_fpu_enabled = 1;
+                       }
+               }
+       }
+
+       if (cm4_fpu_enabled == 1) {
+               /* Read the LR to decide between stacking with or without FPU */
+               uint32_t LR_svc;
+               retval = target_read_u32(rtos->target, stack_ptr + 0x20, 
&LR_svc);
+               if (retval != ERROR_OK) {
+                       LOG_OUTPUT("Error reading stack frame from rtkernel 
thread\r\n");
+                       return retval;
+               }
+               if ((LR_svc & 0x10) == 0) {
+                       LOG_DEBUG("cm4f_fpu stacking");
+                       return rtos_generic_stack_read(rtos->target, 
param->stacking_info_cm4f_fpu, stack_ptr, reg_list, num_regs);
+               } else {
+                       LOG_DEBUG("cm4f stacking");
+                       return rtos_generic_stack_read(rtos->target, 
param->stacking_info_cm4f, stack_ptr, reg_list, num_regs);
+               }
+       } else {
+               LOG_DEBUG("cm3 stacking");
+               return rtos_generic_stack_read(rtos->target, 
param->stacking_info_cm3, stack_ptr, reg_list, num_regs);
+       }
+}
+
+static int rtkernel_get_symbol_list_to_lookup(struct symbol_table_elem 
*symbol_list[])
+{
+       unsigned int i;
+       *symbol_list = calloc(
+                       ARRAY_SIZE(rtkernel_symbol_list), sizeof(struct 
symbol_table_elem));
+
+       for (i = 0; i < ARRAY_SIZE(rtkernel_symbol_list); i++) {
+               (*symbol_list)[i].symbol_name = rtkernel_symbol_list[i].name;
+               (*symbol_list)[i].optional = rtkernel_symbol_list[i].optional;
+       }
+
+       return 0;
+}
+
+static bool rtkernel_detect_rtos(struct target *target)
+{
+       return (target->rtos->symbols != NULL) &&
+                       
(target->rtos->symbols[sym___off_os_state2chain].address != 0);
+}
+
+static int rtkernel_create(struct target *target)
+{
+       for (int i = 0; i < RTKERNEL_NUM_PARAMS; i++) {
+               if (strcmp(rtkernel_params_list[i].target_name, 
target->type->name) == 0) {
+                       target->rtos->rtos_specific_params = (void *) 
&rtkernel_params_list[i];
+                       return 0;
+               }
+       }
+
+       LOG_ERROR("Could not find target in rt-kernel compatibility list");
+       return -1;
+}
diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
index f401c3d30..5093f24fa 100644
--- a/src/rtos/rtos.c
+++ b/src/rtos/rtos.c
@@ -40,6 +40,7 @@ extern struct rtos_type nuttx_rtos;
 extern struct rtos_type hwthread_rtos;
 extern struct rtos_type riot_rtos;
 extern struct rtos_type zephyr_rtos;
+extern struct rtos_type rtkernel_rtos;
 
 static struct rtos_type *rtos_types[] = {
        &threadx_rtos,
@@ -54,6 +55,7 @@ static struct rtos_type *rtos_types[] = {
        &nuttx_rtos,
        &riot_rtos,
        &zephyr_rtos,
+       &rtkernel_rtos,
        /* keep this as last, as it always matches with rtos auto */
        &hwthread_rtos,
        NULL

-- 

Reply via email to