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"
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 /* see arch/arm/include/armv7-m/irq_cmnvector.h */
89 static const struct stack_register_offset nuttx_stack_offsets_cortex_m
[] = {
90 { ARMV7M_R0
, 0x28, 32 }, /* r0 */
91 { ARMV7M_R1
, 0x2c, 32 }, /* r1 */
92 { ARMV7M_R2
, 0x30, 32 }, /* r2 */
93 { ARMV7M_R3
, 0x34, 32 }, /* r3 */
94 { ARMV7M_R4
, 0x08, 32 }, /* r4 */
95 { ARMV7M_R5
, 0x0c, 32 }, /* r5 */
96 { ARMV7M_R6
, 0x10, 32 }, /* r6 */
97 { ARMV7M_R7
, 0x14, 32 }, /* r7 */
98 { ARMV7M_R8
, 0x18, 32 }, /* r8 */
99 { ARMV7M_R9
, 0x1c, 32 }, /* r9 */
100 { ARMV7M_R10
, 0x20, 32 }, /* r10 */
101 { ARMV7M_R11
, 0x24, 32 }, /* r11 */
102 { ARMV7M_R12
, 0x38, 32 }, /* r12 */
103 { ARMV7M_R13
, 0, 32 }, /* sp */
104 { ARMV7M_R14
, 0x3c, 32 }, /* lr */
105 { ARMV7M_PC
, 0x40, 32 }, /* pc */
106 { ARMV7M_xPSR
, 0x44, 32 }, /* xPSR */
110 static const struct rtos_register_stacking nuttx_stacking_cortex_m
= {
111 .stack_registers_size
= 0x48,
112 .stack_growth_direction
= -1,
113 .num_output_registers
= 17,
114 .register_offsets
= nuttx_stack_offsets_cortex_m
117 static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu
[] = {
118 { ARMV7M_R0
, 0x6c, 32 }, /* r0 */
119 { ARMV7M_R1
, 0x70, 32 }, /* r1 */
120 { ARMV7M_R2
, 0x74, 32 }, /* r2 */
121 { ARMV7M_R3
, 0x78, 32 }, /* r3 */
122 { ARMV7M_R4
, 0x08, 32 }, /* r4 */
123 { ARMV7M_R5
, 0x0c, 32 }, /* r5 */
124 { ARMV7M_R6
, 0x10, 32 }, /* r6 */
125 { ARMV7M_R7
, 0x14, 32 }, /* r7 */
126 { ARMV7M_R8
, 0x18, 32 }, /* r8 */
127 { ARMV7M_R9
, 0x1c, 32 }, /* r9 */
128 { ARMV7M_R10
, 0x20, 32 }, /* r10 */
129 { ARMV7M_R11
, 0x24, 32 }, /* r11 */
130 { ARMV7M_R12
, 0x7c, 32 }, /* r12 */
131 { ARMV7M_R13
, 0, 32 }, /* sp */
132 { ARMV7M_R14
, 0x80, 32 }, /* lr */
133 { ARMV7M_PC
, 0x84, 32 }, /* pc */
134 { ARMV7M_xPSR
, 0x88, 32 }, /* xPSR */
137 static const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu
= {
138 .stack_registers_size
= 0x8c,
139 .stack_growth_direction
= -1,
140 .num_output_registers
= 17,
141 .register_offsets
= nuttx_stack_offsets_cortex_m_fpu
144 static int pid_offset
= PID
;
145 static int state_offset
= STATE
;
146 static int name_offset
= NAME
;
147 static int xcpreg_offset
= XCPREG
;
148 static int name_size
= NAME_SIZE
;
150 static int rcmd_offset(const char *cmd
, const char *name
)
152 if (strncmp(cmd
, name
, strlen(name
)))
155 if (strlen(cmd
) <= strlen(name
) + 1)
158 return atoi(cmd
+ strlen(name
));
161 static int nuttx_thread_packet(struct connection
*connection
,
162 char const *packet
, int packet_size
)
164 char cmd
[GDB_BUFFER_SIZE
/ 2 + 1] = ""; /* Extra byte for null-termination */
166 if (!strncmp(packet
, "qRcmd", 5)) {
167 size_t len
= unhexify((uint8_t *)cmd
, packet
+ 6, sizeof(cmd
));
173 offset
= rcmd_offset(cmd
, "nuttx.pid_offset");
176 LOG_INFO("pid_offset: %d", offset
);
181 offset
= rcmd_offset(cmd
, "nuttx.state_offset");
184 LOG_INFO("state_offset: %d", offset
);
185 state_offset
= offset
;
189 offset
= rcmd_offset(cmd
, "nuttx.name_offset");
192 LOG_INFO("name_offset: %d", offset
);
193 name_offset
= offset
;
197 offset
= rcmd_offset(cmd
, "nuttx.xcpreg_offset");
200 LOG_INFO("xcpreg_offset: %d", offset
);
201 xcpreg_offset
= offset
;
205 offset
= rcmd_offset(cmd
, "nuttx.name_size");
208 LOG_INFO("name_size: %d", offset
);
214 return rtos_thread_packet(connection
, packet
, packet_size
);
216 gdb_put_packet(connection
, "OK", 2);
221 static bool nuttx_detect_rtos(struct target
*target
)
223 if ((target
->rtos
->symbols
) &&
224 (target
->rtos
->symbols
[0].address
!= 0) &&
225 (target
->rtos
->symbols
[1].address
!= 0)) {
231 static int nuttx_create(struct target
*target
)
234 target
->rtos
->gdb_thread_packet
= nuttx_thread_packet
;
235 LOG_INFO("target type name = %s", target
->type
->name
);
239 static int nuttx_update_threads(struct rtos
*rtos
)
241 uint32_t thread_count
;
249 if (!rtos
->symbols
) {
250 LOG_ERROR("No symbols for NuttX");
254 /* free previous thread details */
255 rtos_free_threadlist(rtos
);
257 ret
= target_read_buffer(rtos
->target
, rtos
->symbols
[1].address
,
258 sizeof(g_tasklist
), (uint8_t *)&g_tasklist
);
260 LOG_ERROR("target_read_buffer : ret = %d\n", ret
);
266 for (i
= 0; i
< TASK_QUEUE_NUM
; i
++) {
268 if (g_tasklist
[i
].addr
== 0)
271 ret
= target_read_u32(rtos
->target
, g_tasklist
[i
].addr
,
275 LOG_ERROR("target_read_u32 : ret = %d\n", ret
);
279 /* readytorun head is current thread */
280 if (g_tasklist
[i
].addr
== rtos
->symbols
[0].address
)
281 rtos
->current_thread
= head
;
286 struct thread_detail
*thread
;
287 ret
= target_read_buffer(rtos
->target
, tcb_addr
,
288 sizeof(tcb
), (uint8_t *)&tcb
);
290 LOG_ERROR("target_read_buffer : ret = %d\n",
296 rtos
->thread_details
= realloc(rtos
->thread_details
,
297 sizeof(struct thread_detail
) * thread_count
);
298 thread
= &rtos
->thread_details
[thread_count
- 1];
299 thread
->threadid
= tcb_addr
;
300 thread
->exists
= true;
302 state
= tcb
.dat
[state_offset
- 8];
303 thread
->extra_info_str
= NULL
;
304 if (state
< ARRAY_SIZE(task_state_str
)) {
305 thread
->extra_info_str
= malloc(256);
306 snprintf(thread
->extra_info_str
, 256, "pid:%d, %s",
307 tcb
.dat
[pid_offset
- 8] |
308 tcb
.dat
[pid_offset
- 8 + 1] << 8,
309 task_state_str
[state
]);
313 thread
->thread_name_str
= malloc(name_size
+ 1);
314 snprintf(thread
->thread_name_str
, name_size
,
315 "%s", (char *)&tcb
.dat
[name_offset
- 8]);
317 thread
->thread_name_str
= malloc(sizeof("None"));
318 strcpy(thread
->thread_name_str
, "None");
321 tcb_addr
= tcb
.flink
;
324 rtos
->thread_count
= thread_count
;
331 * thread_id = tcb address;
333 static int nuttx_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
334 struct rtos_reg
**reg_list
, int *num_regs
)
338 /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */
339 bool cm4_fpu_enabled
= false;
340 struct armv7m_common
*armv7m_target
= target_to_armv7m(rtos
->target
);
341 if (is_armv7m(armv7m_target
)) {
342 if (armv7m_target
->fp_feature
== FPV4_SP
) {
343 /* Found ARM v7m target which includes a FPU */
346 retval
= target_read_u32(rtos
->target
, FPU_CPACR
, &cpacr
);
347 if (retval
!= ERROR_OK
) {
348 LOG_ERROR("Could not read CPACR register to check FPU state");
352 /* Check if CP10 and CP11 are set to full access. */
353 if (cpacr
& 0x00F00000) {
354 /* Found target with enabled FPU */
360 const struct rtos_register_stacking
*stacking
;
362 stacking
= &nuttx_stacking_cortex_m_fpu
;
364 stacking
= &nuttx_stacking_cortex_m
;
366 return rtos_generic_stack_read(rtos
->target
, stacking
,
367 (uint32_t)thread_id
+ xcpreg_offset
, reg_list
, num_regs
);
370 static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
374 *symbol_list
= (struct symbol_table_elem
*) calloc(1,
375 sizeof(struct symbol_table_elem
) * ARRAY_SIZE(nuttx_symbol_list
));
377 for (i
= 0; i
< ARRAY_SIZE(nuttx_symbol_list
); i
++)
378 (*symbol_list
)[i
].symbol_name
= nuttx_symbol_list
[i
];
383 struct rtos_type nuttx_rtos
= {
385 .detect_rtos
= nuttx_detect_rtos
,
386 .create
= nuttx_create
,
387 .update_threads
= nuttx_update_threads
,
388 .get_thread_reg_list
= nuttx_get_thread_reg_list
,
389 .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)