1 /***************************************************************************
2 * Copyright 2016,2017 Sony Video & Sound Products Inc. *
3 * Masatoshi Tateishi - Masatoshi.Tateishi@jp.sony.com *
4 * Masayuki Ishikawa - Masayuki.Ishikawa@jp.sony.com *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 ***************************************************************************/
24 #include <jtag/jtag.h>
25 #include "target/target.h"
26 #include "target/target_type.h"
27 #include "target/armv7m.h"
28 #include "target/cortex_m.h"
30 #include "helper/log.h"
31 #include "helper/types.h"
32 #include "server/gdb_server.h"
34 #include "nuttx_header.h"
37 int rtos_thread_packet(struct connection
*connection
, const char *packet
, int packet_size
);
39 #ifdef CONFIG_DISABLE_SIGNALS
40 #define SIG_QUEUE_NUM 0
42 #define SIG_QUEUE_NUM 1
43 #endif /* CONFIG_DISABLE_SIGNALS */
45 #ifdef CONFIG_DISABLE_MQUEUE
49 #endif /* CONFIG_DISABLE_MQUEUE */
52 #define PAGING_QUEUE_NUM 1
54 #define PAGING_QUEUE_NUM 0
55 #endif /* CONFIG_PAGING */
58 #define TASK_QUEUE_NUM (6 + SIG_QUEUE_NUM + M_QUEUE_NUM + PAGING_QUEUE_NUM)
61 /* see nuttx/sched/os_start.c */
62 static char *nuttx_symbol_list
[] = {
63 "g_readytorun", /* 0: must be top of this array */
68 /* see nuttx/include/nuttx/sched.h */
78 } g_tasklist
[TASK_QUEUE_NUM
];
80 static char *task_state_str
[] = {
87 #ifndef CONFIG_DISABLE_SIGNALS
89 #endif /* CONFIG_DISABLE_SIGNALS */
90 #ifndef CONFIG_DISABLE_MQUEUE
93 #endif /* CONFIG_DISABLE_MQUEUE */
96 #endif /* CONFIG_PAGING */
99 /* see arch/arm/include/armv7-m/irq_cmnvector.h */
100 static const struct stack_register_offset nuttx_stack_offsets_cortex_m
[] = {
101 { ARMV7M_R0
, 0x28, 32 }, /* r0 */
102 { ARMV7M_R1
, 0x2c, 32 }, /* r1 */
103 { ARMV7M_R2
, 0x30, 32 }, /* r2 */
104 { ARMV7M_R3
, 0x34, 32 }, /* r3 */
105 { ARMV7M_R4
, 0x08, 32 }, /* r4 */
106 { ARMV7M_R5
, 0x0c, 32 }, /* r5 */
107 { ARMV7M_R6
, 0x10, 32 }, /* r6 */
108 { ARMV7M_R7
, 0x14, 32 }, /* r7 */
109 { ARMV7M_R8
, 0x18, 32 }, /* r8 */
110 { ARMV7M_R9
, 0x1c, 32 }, /* r9 */
111 { ARMV7M_R10
, 0x20, 32 }, /* r10 */
112 { ARMV7M_R11
, 0x24, 32 }, /* r11 */
113 { ARMV7M_R12
, 0x38, 32 }, /* r12 */
114 { ARMV7M_R13
, 0, 32 }, /* sp */
115 { ARMV7M_R14
, 0x3c, 32 }, /* lr */
116 { ARMV7M_PC
, 0x40, 32 }, /* pc */
117 { ARMV7M_xPSR
, 0x44, 32 }, /* xPSR */
121 static const struct rtos_register_stacking nuttx_stacking_cortex_m
= {
122 .stack_registers_size
= 0x48,
123 .stack_growth_direction
= -1,
124 .num_output_registers
= 17,
125 .register_offsets
= nuttx_stack_offsets_cortex_m
128 static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu
[] = {
129 { ARMV7M_R0
, 0x6c, 32 }, /* r0 */
130 { ARMV7M_R1
, 0x70, 32 }, /* r1 */
131 { ARMV7M_R2
, 0x74, 32 }, /* r2 */
132 { ARMV7M_R3
, 0x78, 32 }, /* r3 */
133 { ARMV7M_R4
, 0x08, 32 }, /* r4 */
134 { ARMV7M_R5
, 0x0c, 32 }, /* r5 */
135 { ARMV7M_R6
, 0x10, 32 }, /* r6 */
136 { ARMV7M_R7
, 0x14, 32 }, /* r7 */
137 { ARMV7M_R8
, 0x18, 32 }, /* r8 */
138 { ARMV7M_R9
, 0x1c, 32 }, /* r9 */
139 { ARMV7M_R10
, 0x20, 32 }, /* r10 */
140 { ARMV7M_R11
, 0x24, 32 }, /* r11 */
141 { ARMV7M_R12
, 0x7c, 32 }, /* r12 */
142 { ARMV7M_R13
, 0, 32 }, /* sp */
143 { ARMV7M_R14
, 0x80, 32 }, /* lr */
144 { ARMV7M_PC
, 0x84, 32 }, /* pc */
145 { ARMV7M_xPSR
, 0x88, 32 }, /* xPSR */
148 static const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu
= {
149 .stack_registers_size
= 0x8c,
150 .stack_growth_direction
= -1,
151 .num_output_registers
= 17,
152 .register_offsets
= nuttx_stack_offsets_cortex_m_fpu
155 static int pid_offset
= PID
;
156 static int state_offset
= STATE
;
157 static int name_offset
= NAME
;
158 static int xcpreg_offset
= XCPREG
;
159 static int name_size
= NAME_SIZE
;
161 static int rcmd_offset(const char *cmd
, const char *name
)
163 if (strncmp(cmd
, name
, strlen(name
)))
166 if (strlen(cmd
) <= strlen(name
) + 1)
169 return atoi(cmd
+ strlen(name
));
172 static int nuttx_thread_packet(struct connection
*connection
,
173 char const *packet
, int packet_size
)
175 char cmd
[GDB_BUFFER_SIZE
/ 2 + 1] = ""; /* Extra byte for null-termination */
177 if (!strncmp(packet
, "qRcmd", 5)) {
178 size_t len
= unhexify((uint8_t *)cmd
, packet
+ 6, sizeof(cmd
));
184 offset
= rcmd_offset(cmd
, "nuttx.pid_offset");
187 LOG_INFO("pid_offset: %d", offset
);
192 offset
= rcmd_offset(cmd
, "nuttx.state_offset");
195 LOG_INFO("state_offset: %d", offset
);
196 state_offset
= offset
;
200 offset
= rcmd_offset(cmd
, "nuttx.name_offset");
203 LOG_INFO("name_offset: %d", offset
);
204 name_offset
= offset
;
208 offset
= rcmd_offset(cmd
, "nuttx.xcpreg_offset");
211 LOG_INFO("xcpreg_offset: %d", offset
);
212 xcpreg_offset
= offset
;
216 offset
= rcmd_offset(cmd
, "nuttx.name_size");
219 LOG_INFO("name_size: %d", offset
);
225 return rtos_thread_packet(connection
, packet
, packet_size
);
227 gdb_put_packet(connection
, "OK", 2);
232 static bool nuttx_detect_rtos(struct target
*target
)
234 if ((target
->rtos
->symbols
) &&
235 (target
->rtos
->symbols
[0].address
!= 0) &&
236 (target
->rtos
->symbols
[1].address
!= 0)) {
242 static int nuttx_create(struct target
*target
)
245 target
->rtos
->gdb_thread_packet
= nuttx_thread_packet
;
246 LOG_INFO("target type name = %s", target
->type
->name
);
250 static int nuttx_update_threads(struct rtos
*rtos
)
252 uint32_t thread_count
;
260 if (!rtos
->symbols
) {
261 LOG_ERROR("No symbols for NuttX");
265 /* free previous thread details */
266 rtos_free_threadlist(rtos
);
268 ret
= target_read_buffer(rtos
->target
, rtos
->symbols
[1].address
,
269 sizeof(g_tasklist
), (uint8_t *)&g_tasklist
);
271 LOG_ERROR("target_read_buffer : ret = %d\n", ret
);
277 for (i
= 0; i
< TASK_QUEUE_NUM
; i
++) {
279 if (g_tasklist
[i
].addr
== 0)
282 ret
= target_read_u32(rtos
->target
, g_tasklist
[i
].addr
,
286 LOG_ERROR("target_read_u32 : ret = %d\n", ret
);
290 /* readytorun head is current thread */
291 if (g_tasklist
[i
].addr
== rtos
->symbols
[0].address
)
292 rtos
->current_thread
= head
;
297 struct thread_detail
*thread
;
298 ret
= target_read_buffer(rtos
->target
, tcb_addr
,
299 sizeof(tcb
), (uint8_t *)&tcb
);
301 LOG_ERROR("target_read_buffer : ret = %d\n",
307 rtos
->thread_details
= realloc(rtos
->thread_details
,
308 sizeof(struct thread_detail
) * thread_count
);
309 thread
= &rtos
->thread_details
[thread_count
- 1];
310 thread
->threadid
= tcb_addr
;
311 thread
->exists
= true;
313 state
= tcb
.dat
[state_offset
- 8];
314 thread
->extra_info_str
= NULL
;
315 if (state
< ARRAY_SIZE(task_state_str
)) {
316 thread
->extra_info_str
= malloc(256);
317 snprintf(thread
->extra_info_str
, 256, "pid:%d, %s",
318 tcb
.dat
[pid_offset
- 8] |
319 tcb
.dat
[pid_offset
- 8 + 1] << 8,
320 task_state_str
[state
]);
324 thread
->thread_name_str
= malloc(name_size
+ 1);
325 snprintf(thread
->thread_name_str
, name_size
,
326 "%s", (char *)&tcb
.dat
[name_offset
- 8]);
328 thread
->thread_name_str
= malloc(sizeof("None"));
329 strcpy(thread
->thread_name_str
, "None");
332 tcb_addr
= tcb
.flink
;
335 rtos
->thread_count
= thread_count
;
342 * thread_id = tcb address;
344 static int nuttx_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
345 struct rtos_reg
**reg_list
, int *num_regs
)
349 /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */
350 bool cm4_fpu_enabled
= false;
351 struct armv7m_common
*armv7m_target
= target_to_armv7m(rtos
->target
);
352 if (is_armv7m(armv7m_target
)) {
353 if (armv7m_target
->fp_feature
== FPV4_SP
) {
354 /* Found ARM v7m target which includes a FPU */
357 retval
= target_read_u32(rtos
->target
, FPU_CPACR
, &cpacr
);
358 if (retval
!= ERROR_OK
) {
359 LOG_ERROR("Could not read CPACR register to check FPU state");
363 /* Check if CP10 and CP11 are set to full access. */
364 if (cpacr
& 0x00F00000) {
365 /* Found target with enabled FPU */
371 const struct rtos_register_stacking
*stacking
;
373 stacking
= &nuttx_stacking_cortex_m_fpu
;
375 stacking
= &nuttx_stacking_cortex_m
;
377 return rtos_generic_stack_read(rtos
->target
, stacking
,
378 (uint32_t)thread_id
+ xcpreg_offset
, reg_list
, num_regs
);
381 static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
385 *symbol_list
= (struct symbol_table_elem
*) calloc(1,
386 sizeof(struct symbol_table_elem
) * ARRAY_SIZE(nuttx_symbol_list
));
388 for (i
= 0; i
< ARRAY_SIZE(nuttx_symbol_list
); i
++)
389 (*symbol_list
)[i
].symbol_name
= nuttx_symbol_list
[i
];
394 struct rtos_type nuttx_rtos
= {
396 .detect_rtos
= nuttx_detect_rtos
,
397 .create
= nuttx_create
,
398 .update_threads
= nuttx_update_threads
,
399 .get_thread_reg_list
= nuttx_get_thread_reg_list
,
400 .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)