1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright 2016,2017 Sony Video & Sound Products Inc. *
5 * Masatoshi Tateishi - Masatoshi.Tateishi@jp.sony.com *
6 * Masayuki Ishikawa - Masayuki.Ishikawa@jp.sony.com *
7 ***************************************************************************/
13 #include <jtag/jtag.h>
14 #include "target/target.h"
15 #include "target/target_type.h"
16 #include "target/armv7m.h"
17 #include "target/cortex_m.h"
19 #include "helper/log.h"
20 #include "helper/types.h"
21 #include "server/gdb_server.h"
23 #include "nuttx_header.h"
24 #include "rtos_nuttx_stackings.h"
26 int rtos_thread_packet(struct connection
*connection
, const char *packet
, int packet_size
);
28 #ifdef CONFIG_DISABLE_SIGNALS
29 #define SIG_QUEUE_NUM 0
31 #define SIG_QUEUE_NUM 1
32 #endif /* CONFIG_DISABLE_SIGNALS */
34 #ifdef CONFIG_DISABLE_MQUEUE
38 #endif /* CONFIG_DISABLE_MQUEUE */
41 #define PAGING_QUEUE_NUM 1
43 #define PAGING_QUEUE_NUM 0
44 #endif /* CONFIG_PAGING */
47 #define TASK_QUEUE_NUM (6 + SIG_QUEUE_NUM + M_QUEUE_NUM + PAGING_QUEUE_NUM)
50 /* see nuttx/sched/os_start.c */
51 static char *nuttx_symbol_list
[] = {
52 "g_readytorun", /* 0: must be top of this array */
57 /* see nuttx/include/nuttx/sched.h */
67 } g_tasklist
[TASK_QUEUE_NUM
];
69 static char *task_state_str
[] = {
76 #ifndef CONFIG_DISABLE_SIGNALS
78 #endif /* CONFIG_DISABLE_SIGNALS */
79 #ifndef CONFIG_DISABLE_MQUEUE
82 #endif /* CONFIG_DISABLE_MQUEUE */
85 #endif /* CONFIG_PAGING */
88 static int pid_offset
= PID
;
89 static int state_offset
= STATE
;
90 static int name_offset
= NAME
;
91 static int xcpreg_offset
= XCPREG
;
92 static int name_size
= NAME_SIZE
;
94 static int rcmd_offset(const char *cmd
, const char *name
)
96 if (strncmp(cmd
, name
, strlen(name
)))
99 if (strlen(cmd
) <= strlen(name
) + 1)
102 return atoi(cmd
+ strlen(name
));
105 static int nuttx_thread_packet(struct connection
*connection
,
106 char const *packet
, int packet_size
)
108 char cmd
[GDB_BUFFER_SIZE
/ 2 + 1] = ""; /* Extra byte for null-termination */
110 if (!strncmp(packet
, "qRcmd", 5)) {
111 size_t len
= unhexify((uint8_t *)cmd
, packet
+ 6, sizeof(cmd
));
117 offset
= rcmd_offset(cmd
, "nuttx.pid_offset");
120 LOG_INFO("pid_offset: %d", offset
);
125 offset
= rcmd_offset(cmd
, "nuttx.state_offset");
128 LOG_INFO("state_offset: %d", offset
);
129 state_offset
= offset
;
133 offset
= rcmd_offset(cmd
, "nuttx.name_offset");
136 LOG_INFO("name_offset: %d", offset
);
137 name_offset
= offset
;
141 offset
= rcmd_offset(cmd
, "nuttx.xcpreg_offset");
144 LOG_INFO("xcpreg_offset: %d", offset
);
145 xcpreg_offset
= offset
;
149 offset
= rcmd_offset(cmd
, "nuttx.name_size");
152 LOG_INFO("name_size: %d", offset
);
158 return rtos_thread_packet(connection
, packet
, packet_size
);
160 gdb_put_packet(connection
, "OK", 2);
165 static bool nuttx_detect_rtos(struct target
*target
)
167 if ((target
->rtos
->symbols
) &&
168 (target
->rtos
->symbols
[0].address
!= 0) &&
169 (target
->rtos
->symbols
[1].address
!= 0)) {
175 static int nuttx_create(struct target
*target
)
178 target
->rtos
->gdb_thread_packet
= nuttx_thread_packet
;
179 LOG_INFO("target type name = %s", target
->type
->name
);
183 static int nuttx_update_threads(struct rtos
*rtos
)
185 uint32_t thread_count
;
193 if (!rtos
->symbols
) {
194 LOG_ERROR("No symbols for NuttX");
198 /* free previous thread details */
199 rtos_free_threadlist(rtos
);
201 ret
= target_read_buffer(rtos
->target
, rtos
->symbols
[1].address
,
202 sizeof(g_tasklist
), (uint8_t *)&g_tasklist
);
204 LOG_ERROR("target_read_buffer : ret = %d\n", ret
);
210 for (i
= 0; i
< TASK_QUEUE_NUM
; i
++) {
212 if (g_tasklist
[i
].addr
== 0)
215 ret
= target_read_u32(rtos
->target
, g_tasklist
[i
].addr
,
219 LOG_ERROR("target_read_u32 : ret = %d\n", ret
);
223 /* readytorun head is current thread */
224 if (g_tasklist
[i
].addr
== rtos
->symbols
[0].address
)
225 rtos
->current_thread
= head
;
230 struct thread_detail
*thread
;
231 ret
= target_read_buffer(rtos
->target
, tcb_addr
,
232 sizeof(tcb
), (uint8_t *)&tcb
);
234 LOG_ERROR("target_read_buffer : ret = %d\n",
240 rtos
->thread_details
= realloc(rtos
->thread_details
,
241 sizeof(struct thread_detail
) * thread_count
);
242 thread
= &rtos
->thread_details
[thread_count
- 1];
243 thread
->threadid
= tcb_addr
;
244 thread
->exists
= true;
246 state
= tcb
.dat
[state_offset
- 8];
247 thread
->extra_info_str
= NULL
;
248 if (state
< ARRAY_SIZE(task_state_str
)) {
249 thread
->extra_info_str
= malloc(256);
250 snprintf(thread
->extra_info_str
, 256, "pid:%d, %s",
251 tcb
.dat
[pid_offset
- 8] |
252 tcb
.dat
[pid_offset
- 8 + 1] << 8,
253 task_state_str
[state
]);
257 thread
->thread_name_str
= malloc(name_size
+ 1);
258 snprintf(thread
->thread_name_str
, name_size
,
259 "%s", (char *)&tcb
.dat
[name_offset
- 8]);
261 thread
->thread_name_str
= malloc(sizeof("None"));
262 strcpy(thread
->thread_name_str
, "None");
265 tcb_addr
= tcb
.flink
;
268 rtos
->thread_count
= thread_count
;
275 * thread_id = tcb address;
277 static int nuttx_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
278 struct rtos_reg
**reg_list
, int *num_regs
)
282 /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */
283 bool cm4_fpu_enabled
= false;
284 struct armv7m_common
*armv7m_target
= target_to_armv7m(rtos
->target
);
285 if (is_armv7m(armv7m_target
)) {
286 if (armv7m_target
->fp_feature
== FPV4_SP
) {
287 /* Found ARM v7m target which includes a FPU */
290 retval
= target_read_u32(rtos
->target
, FPU_CPACR
, &cpacr
);
291 if (retval
!= ERROR_OK
) {
292 LOG_ERROR("Could not read CPACR register to check FPU state");
296 /* Check if CP10 and CP11 are set to full access. */
297 if (cpacr
& 0x00F00000) {
298 /* Found target with enabled FPU */
304 const struct rtos_register_stacking
*stacking
;
306 stacking
= &nuttx_stacking_cortex_m_fpu
;
308 stacking
= &nuttx_stacking_cortex_m
;
310 return rtos_generic_stack_read(rtos
->target
, stacking
,
311 (uint32_t)thread_id
+ xcpreg_offset
, reg_list
, num_regs
);
314 static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
318 *symbol_list
= (struct symbol_table_elem
*) calloc(1,
319 sizeof(struct symbol_table_elem
) * ARRAY_SIZE(nuttx_symbol_list
));
321 for (i
= 0; i
< ARRAY_SIZE(nuttx_symbol_list
); i
++)
322 (*symbol_list
)[i
].symbol_name
= nuttx_symbol_list
[i
];
327 const struct rtos_type nuttx_rtos
= {
329 .detect_rtos
= nuttx_detect_rtos
,
330 .create
= nuttx_create
,
331 .update_threads
= nuttx_update_threads
,
332 .get_thread_reg_list
= nuttx_get_thread_reg_list
,
333 .get_symbol_list_to_lookup
= nuttx_get_symbol_list_to_lookup
,
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)