Discussion:
[OpenOCD-devel] [PATCH]: f494571 rtos: add nuttx thread support
gerrit
2017-04-09 23:59:25 UTC
Permalink
This is an automated email from Gerrit.

Masayuki Ishikawa (***@jp.sony.com) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4103

-- gerrit

commit f4945718e07e768a0e663ad384aa0f25308a35bb
Author: Masatoshi Tateishi <***@jp.sony.com>
Date: Mon Apr 10 08:48:44 2017 +0900

rtos: add nuttx thread support

To use, add the following lines to ~/.gdbinit.

define hookpost-file
eval "monitor nuttx.pid_offset %d", &((struct tcb_s *)(0))->pid
eval "monitor nuttx.xcpreg_offset %d", &((struct tcb_s *)(0))->xcp.regs
eval "monitor nuttx.state_offset %d", &((struct tcb_s *)(0))->task_state
eval "monitor nuttx.name_offset %d", &((struct tcb_s *)(0))->name
eval "monitor nuttx.name_size %d", sizeof(((struct tcb_s *)(0))->name)
end

Change-Id: I2aaf8644d24dfb84b500516a9685382d5d8fe48f
Signed-off-by: Masayuki Ishikawa <***@jp.sony.com>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index c3053b7..c97904b 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -4170,7 +4170,7 @@ The value should normally correspond to a static mapping for the
@item @code{-rtos} @var{rtos_type} -- enable rtos support for target,
@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{embKernel}, @option{mqx}, @option{uCOS-III}, @option{nuttx}
@xref{gdbrtossupport,,RTOS Support}.

@item @code{-defer-examine} -- skip target examination at initial JTAG chain
@@ -8937,6 +8937,7 @@ Currently supported rtos's include:
@item @option{embKernel}
@item @option{mqx}
@item @option{uCOS-III}
+@item @option{nuttx}
@end itemize

@quotation Note
@@ -8972,6 +8973,8 @@ Rtos::sListSuspended, Rtos::sMaxPriorities, Rtos::sCurrentTaskCount.
_mqx_kernel_data, MQX_init_struct.
@item uC/OS-III symbols
OSRunning, OSTCBCurPtr, OSTaskDbgListPtr, OSTaskQty
+@item nuttx symbols
+g_readytorun, g_tasklisttable
@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 c59ee3f..c8c4023 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%/nuttx.c \
%D%/rtos.h \
%D%/rtos_standard_stackings.h \
%D%/rtos_ecos_stackings.h \
@@ -22,7 +23,8 @@ noinst_LTLIBRARIES += %D%/librtos.la
%D%/rtos_chibios_stackings.h \
%D%/rtos_embkernel_stackings.h \
%D%/rtos_mqx_stackings.h \
- %D%/rtos_ucos_iii_stackings.h
+ %D%/rtos_ucos_iii_stackings.h \
+ %D%/nuttx_header.h

%C%_librtos_la_CFLAGS = $(AM_CFLAGS)

diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c
new file mode 100644
index 0000000..5e108ec
--- /dev/null
+++ b/src/rtos/nuttx.c
@@ -0,0 +1,343 @@
+/***************************************************************************
+ * Copyright (C) 2016-2017 by Sony Corporation *
+ * Masatoshi Tateishi - ***@jp.sony.com *
+ * Masayuki Ishikawa - ***@jp.sony.com *
+ * *
+ * 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 <jtag/jtag.h>
+#include "target/target.h"
+#include "target/target_type.h"
+#include "target/armv7m.h"
+#include "target/cortex_m.h"
+#include "rtos.h"
+#include "helper/log.h"
+#include "helper/types.h"
+#include "server/gdb_server.h"
+
+#include "nuttx_header.h"
+
+
+int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
+
+#ifdef CONFIG_DISABLE_SIGNALS
+#define SIG_QUEUE_NUM 0
+#else
+#define SIG_QUEUE_NUM 1
+#endif /* CONFIG_DISABLE_SIGNALS */
+
+#ifdef CONFIG_DISABLE_MQUEUE
+#define M_QUEUE_NUM 0
+#else
+#define M_QUEUE_NUM 2
+#endif /* CONFIG_DISABLE_MQUEUE */
+
+#ifdef CONFIG_PAGING
+#define PAGING_QUEUE_NUM 1
+#else
+#define PAGING_QUEUE_NUM 0
+#endif /* CONFIG_PAGING */
+
+
+#define TASK_QUEUE_NUM (6 + SIG_QUEUE_NUM + M_QUEUE_NUM + PAGING_QUEUE_NUM)
+
+
+/* see nuttx/sched/os_start.c */
+static char *nuttx_symbol_list[] = {
+ "g_readytorun", /* 0: must be top of this array */
+ "g_tasklisttable",
+ NULL
+};
+
+/* see nuttx/include/nuttx/sched.h */
+struct tcb_s {
+ uint32_t flink;
+ uint32_t blink;
+ uint8_t dat[256];
+};
+
+struct {
+ uint32_t addr;
+ uint32_t prio;
+} g_tasklist[TASK_QUEUE_NUM];
+
+static char *task_state_str[] = {
+ "INVALID",
+ "PENDING",
+ "READYTORUN",
+ "RUNNING",
+ "INACTIVE",
+ "WAIT_SEM",
+#ifndef CONFIG_DISABLE_SIGNALS
+ "WAIT_SIG",
+#endif /* CONFIG_DISABLE_SIGNALS */
+#ifndef CONFIG_DISABLE_MQUEUE
+ "WAIT_MQNOTEMPTY",
+ "WAIT_MQNOTFULL",
+#endif /* CONFIG_DISABLE_MQUEUE */
+#ifdef CONFIG_PAGING
+ "WAIT_PAGEFILL",
+#endif /* CONFIG_PAGING */
+};
+
+/* see arch/arm/include/armv7-m/irq_cmnvector.h */
+static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = {
+ { 0x28, 32 }, /* r0 */
+ { 0x2c, 32 }, /* r1 */
+ { 0x30, 32 }, /* r2 */
+ { 0x34, 32 }, /* r3 */
+ { 0x08, 32 }, /* r4 */
+ { 0x0c, 32 }, /* r5 */
+ { 0x10, 32 }, /* r6 */
+ { 0x14, 32 }, /* r7 */
+ { 0x18, 32 }, /* r8 */
+ { 0x1c, 32 }, /* r9 */
+ { 0x20, 32 }, /* r10 */
+ { 0x24, 32 }, /* r11 */
+ { 0x38, 32 }, /* r12 */
+ { 0, 32 }, /* sp */
+ { 0x3c, 32 }, /* lr */
+ { 0x40, 32 }, /* pc */
+ { 0x44, 32 }, /* xPSR */
+};
+
+
+static const struct rtos_register_stacking nuttx_stacking_cortex_m = {
+ 0x48, /* stack_registers_size */
+ -1, /* stack_growth_direction */
+ 17, /* num_output_registers */
+ 0, /* stack_alignment */
+ nuttx_stack_offsets_cortex_m /* register_offsets */
+};
+
+static uint8_t pid_offset = PID;
+static uint8_t state_offset = STATE;
+static uint8_t name_offset = NAME;
+static uint8_t xcpreg_offset = XCPREG;
+static uint8_t name_size = NAME_SIZE;
+
+static int rcmd_offset(const char *cmd, const char *name)
+{
+ if (strncmp(cmd, name, strlen(name)))
+ return -1;
+
+ if (strlen(cmd) <= strlen(name) + 1)
+ return -1;
+
+ return atoi(cmd + strlen(name));
+}
+
+static int nuttx_thread_packet(struct connection *connection,
+ char const *packet, int packet_size)
+{
+ char cmd[GDB_BUFFER_SIZE / 2] = "";
+
+ if (!strncmp(packet, "qRcmd", 5)) {
+ int len = unhexify((uint8_t *)cmd, packet + 6, sizeof(cmd));
+ int offset;
+
+ if (len <= 0)
+ goto pass;
+
+ offset = rcmd_offset(cmd, "nuttx.pid_offset");
+
+ if (offset >= 0) {
+ LOG_INFO("pid_offset: %d", offset);
+ pid_offset = offset;
+ goto retok;
+ }
+
+ offset = rcmd_offset(cmd, "nuttx.state_offset");
+
+ if (offset >= 0) {
+ LOG_INFO("state_offset: %d", offset);
+ state_offset = offset;
+ goto retok;
+ }
+
+ offset = rcmd_offset(cmd, "nuttx.name_offset");
+
+ if (offset >= 0) {
+ LOG_INFO("name_offset: %d", offset);
+ name_offset = offset;
+ goto retok;
+ }
+
+ offset = rcmd_offset(cmd, "nuttx.xcpreg_offset");
+
+ if (offset >= 0) {
+ LOG_INFO("xcpreg_offset: %d", offset);
+ xcpreg_offset = offset;
+ goto retok;
+ }
+
+ offset = rcmd_offset(cmd, "nuttx.name_size");
+
+ if (offset >= 0) {
+ LOG_INFO("name_size: %d", offset);
+ name_size = offset;
+ goto retok;
+ }
+
+ }
+pass:
+ return rtos_thread_packet(connection, packet, packet_size);
+retok:
+ gdb_put_packet(connection, "OK", 2);
+ return ERROR_OK;
+}
+
+
+static int nuttx_detect_rtos(struct target *target)
+{
+ if ((target->rtos->symbols != NULL) &&
+ (target->rtos->symbols[0].address != 0) &&
+ (target->rtos->symbols[1].address != 0)) {
+ return 1;
+ }
+ return 0;
+}
+
+static int nuttx_create(struct target *target)
+{
+
+ target->rtos->gdb_thread_packet = nuttx_thread_packet;
+ LOG_INFO("target type name = %s", target->type->name);
+ return 0;
+}
+
+static int nuttx_update_threads(struct rtos *rtos)
+{
+ int thread_count;
+ struct tcb_s tcb;
+ int ret;
+ uint32_t head;
+ uint32_t tcb_addr;
+ int i;
+
+ thread_count = 0;
+
+ /* free old thread info */
+ if (rtos->thread_details) {
+ for (i = 0; i < rtos->thread_count; i++) {
+ if (rtos->thread_details[i].thread_name_str)
+ free(rtos->thread_details[i].thread_name_str);
+ }
+
+ free(rtos->thread_details);
+ rtos->thread_details = NULL;
+ rtos->thread_count = 0;
+ }
+
+ ret = target_read_buffer(rtos->target, rtos->symbols[1].address,
+ sizeof(g_tasklist), (uint8_t *)&g_tasklist);
+ if (ret) {
+ LOG_ERROR("target_read_buffer : ret = %d\n", ret);
+ return ERROR_FAIL;
+ }
+
+ for (i = 0; i < (int)TASK_QUEUE_NUM; i++) {
+
+ if (g_tasklist[i].addr == 0)
+ continue;
+
+ ret = target_read_u32(rtos->target, g_tasklist[i].addr,
+ &head);
+
+ if (ret) {
+ LOG_ERROR("target_read_u32 : ret = %d\n", ret);
+ return ERROR_FAIL;
+ }
+
+ /* readytorun head is current thread */
+ if (g_tasklist[i].addr == rtos->symbols[0].address)
+ rtos->current_thread = head;
+
+
+ tcb_addr = head;
+ while (tcb_addr) {
+ struct thread_detail *thread;
+ ret = target_read_buffer(rtos->target, tcb_addr,
+ sizeof(tcb), (uint8_t *)&tcb);
+ if (ret) {
+ LOG_ERROR("target_read_buffer : ret = %d\n",
+ ret);
+ return ERROR_FAIL;
+ }
+ thread_count++;
+
+ rtos->thread_details = realloc(rtos->thread_details,
+ sizeof(struct thread_detail) * thread_count);
+ thread = &rtos->thread_details[thread_count - 1];
+ thread->threadid = tcb_addr;
+ thread->exists = true;
+
+ if (name_offset) {
+ thread->thread_name_str = malloc(name_size + 1);
+ snprintf(thread->thread_name_str, name_size,
+ "%s", (char *)&tcb.dat[name_offset - 8]);
+ } else
+ thread->thread_name_str = NULL;
+
+ thread->extra_info_str =
+ task_state_str[tcb.dat[state_offset - 8]];
+ tcb_addr = tcb.flink;
+ }
+ }
+ rtos->thread_count = thread_count;
+
+ return 0;
+}
+
+
+/*
+ * thread_id = tcb address;
+ */
+static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+ char **hex_reg_list) {
+
+ LOG_DEBUG("*** thread_id=%ld (0x%08x)", thread_id, (int32_t)thread_id);
+ *hex_reg_list = NULL;
+
+ return rtos_generic_stack_read(rtos->target, &nuttx_stacking_cortex_m,
+ (uint32_t)thread_id + xcpreg_offset, hex_reg_list);
+};
+
+static int nuttx_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
+{
+ unsigned int i;
+
+ *symbol_list = (symbol_table_elem_t *) calloc(1,
+ sizeof(symbol_table_elem_t) * ARRAY_SIZE(nuttx_symbol_list));
+
+ for (i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++)
+ (*symbol_list)[i].symbol_name = nuttx_symbol_list[i];
+
+ return 0;
+}
+
+struct rtos_type nuttx_rtos = {
+ .name = "nuttx",
+ .detect_rtos = nuttx_detect_rtos,
+ .create = nuttx_create,
+ .update_threads = nuttx_update_threads,
+ .get_thread_reg_list = nuttx_get_thread_reg_list,
+ .get_symbol_list_to_lookup = nuttx_get_symbol_list_to_lookup,
+};
+
diff --git a/src/rtos/nuttx_header.h b/src/rtos/nuttx_header.h
new file mode 100644
index 0000000..d14372c
--- /dev/null
+++ b/src/rtos/nuttx_header.h
@@ -0,0 +1,71 @@
+#ifndef OPENOCD_RTOS_NUTTX_HEADER_H
+#define OPENOCD_RTOS_NUTTX_HEADER_H
+
+/***************************************************************************
+ * Copyright (C) 2016-2017 by Sony Corporation *
+ * Masatoshi Tateishi - ***@jp.sony.com *
+ * Masayuki Ishikawa - ***@jp.sony.com *
+ * *
+ * 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/>. *
+ ***************************************************************************/
+
+/* gdb script to update the header file
+ according to kernel version and build option
+ before executing function awareness
+ kernel symbol must be loaded : symbol nuttx
+
+define awareness
+ set logging off
+ set logging file nuttx_header.h
+ set logging on
+
+ printf "#define PID %p\n",&((struct tcb_s *)(0))->pid
+ printf "#define XCPREG %p\n",&((struct tcb_s *)(0))->xcp.regs
+ printf "#define STATE %p\n",&((struct tcb_s *)(0))->task_state
+ printf "#define NAME %p\n",&((struct tcb_s *)(0))->name
+ printf "#define NAME_SIZE %d\n",sizeof(((struct tcb_s *)(0))->name)
+ end
+
+
+ OR ~/.gdbinit
+
+
+define hookpost-file
+
+ if &g_readytorun != 0
+ eval "monitor nuttx.pid_offset %d", &((struct tcb_s *)(0))->pid
+ eval "monitor nuttx.xcpreg_offset %d", &((struct tcb_s *)(0))->xcp.regs
+ eval "monitor nuttx.state_offset %d", &((struct tcb_s *)(0))->task_state
+ eval "monitor nuttx.name_offset %d", &((struct tcb_s *)(0))->name
+ eval "monitor nuttx.name_size %d", sizeof(((struct tcb_s *)(0))->name)
+ end
+
+end
+
+*/
+
+/* default offset */
+#define PID 0xc
+#define XCPREG 0x70
+#define STATE 0x19
+#define NAME 0xb8
+#define NAME_SIZE 32
+
+/* defconfig of nuttx */
+/* #define CONFIG_DISABLE_SIGNALS */
+#define CONFIG_DISABLE_MQUEUE
+/* #define CONFIG_PAGING */
+
+
+#endif /* OPENOCD_RTOS_NUTTX_HEADER_H */
diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
index 84ee498..45a6e65 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 nuttx_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,
+ &nuttx_rtos,
NULL
};


--

Loading...