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 0x48, /* stack_registers_size */
123 -1, /* stack_growth_direction */
124 17, /* num_output_registers */
125 0, /* stack_alignment */
126 nuttx_stack_offsets_cortex_m
/* register_offsets */
129 static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu
[] = {
130 { ARMV7M_R0
, 0x6c, 32 }, /* r0 */
131 { ARMV7M_R1
, 0x70, 32 }, /* r1 */
132 { ARMV7M_R2
, 0x74, 32 }, /* r2 */
133 { ARMV7M_R3
, 0x78, 32 }, /* r3 */
134 { ARMV7M_R4
, 0x08, 32 }, /* r4 */
135 { ARMV7M_R5
, 0x0c, 32 }, /* r5 */
136 { ARMV7M_R6
, 0x10, 32 }, /* r6 */
137 { ARMV7M_R7
, 0x14, 32 }, /* r7 */
138 { ARMV7M_R8
, 0x18, 32 }, /* r8 */
139 { ARMV7M_R9
, 0x1c, 32 }, /* r9 */
140 { ARMV7M_R10
, 0x20, 32 }, /* r10 */
141 { ARMV7M_R11
, 0x24, 32 }, /* r11 */
142 { ARMV7M_R12
, 0x7c, 32 }, /* r12 */
143 { ARMV7M_R13
, 0, 32 }, /* sp */
144 { ARMV7M_R14
, 0x80, 32 }, /* lr */
145 { ARMV7M_PC
, 0x84, 32 }, /* pc */
146 { ARMV7M_xPSR
, 0x88, 32 }, /* xPSR */
149 static const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu
= {
150 0x8c, /* stack_registers_size */
151 -1, /* stack_growth_direction */
152 17, /* num_output_registers */
153 0, /* stack_alignment */
154 nuttx_stack_offsets_cortex_m_fpu
/* register_offsets */
157 static int pid_offset
= PID
;
158 static int state_offset
= STATE
;
159 static int name_offset
= NAME
;
160 static int xcpreg_offset
= XCPREG
;
161 static int name_size
= NAME_SIZE
;
163 static int rcmd_offset(const char *cmd
, const char *name
)
165 if (strncmp(cmd
, name
, strlen(name
)))
168 if (strlen(cmd
) <= strlen(name
) + 1)
171 return atoi(cmd
+ strlen(name
));
174 static int nuttx_thread_packet(struct connection
*connection
,
175 char const *packet
, int packet_size
)
177 char cmd
[GDB_BUFFER_SIZE
/ 2 + 1] = ""; /* Extra byte for null-termination */
179 if (!strncmp(packet
, "qRcmd", 5)) {
180 size_t len
= unhexify((uint8_t *)cmd
, packet
+ 6, sizeof(cmd
));
186 offset
= rcmd_offset(cmd
, "nuttx.pid_offset");
189 LOG_INFO("pid_offset: %d", offset
);
194 offset
= rcmd_offset(cmd
, "nuttx.state_offset");
197 LOG_INFO("state_offset: %d", offset
);
198 state_offset
= offset
;
202 offset
= rcmd_offset(cmd
, "nuttx.name_offset");
205 LOG_INFO("name_offset: %d", offset
);
206 name_offset
= offset
;
210 offset
= rcmd_offset(cmd
, "nuttx.xcpreg_offset");
213 LOG_INFO("xcpreg_offset: %d", offset
);
214 xcpreg_offset
= offset
;
218 offset
= rcmd_offset(cmd
, "nuttx.name_size");
221 LOG_INFO("name_size: %d", offset
);
227 return rtos_thread_packet(connection
, packet
, packet_size
);
229 gdb_put_packet(connection
, "OK", 2);
234 static bool nuttx_detect_rtos(struct target
*target
)
236 if ((target
->rtos
->symbols
) &&
237 (target
->rtos
->symbols
[0].address
!= 0) &&
238 (target
->rtos
->symbols
[1].address
!= 0)) {
244 static int nuttx_create(struct target
*target
)
247 target
->rtos
->gdb_thread_packet
= nuttx_thread_packet
;
248 LOG_INFO("target type name = %s", target
->type
->name
);
252 static int nuttx_update_threads(struct rtos
*rtos
)
254 uint32_t thread_count
;
262 if (!rtos
->symbols
) {
263 LOG_ERROR("No symbols for NuttX");
267 /* free previous thread details */
268 rtos_free_threadlist(rtos
);
270 ret
= target_read_buffer(rtos
->target
, rtos
->symbols
[1].address
,
271 sizeof(g_tasklist
), (uint8_t *)&g_tasklist
);
273 LOG_ERROR("target_read_buffer : ret = %d\n", ret
);
279 for (i
= 0; i
< TASK_QUEUE_NUM
; i
++) {
281 if (g_tasklist
[i
].addr
== 0)
284 ret
= target_read_u32(rtos
->target
, g_tasklist
[i
].addr
,
288 LOG_ERROR("target_read_u32 : ret = %d\n", ret
);
292 /* readytorun head is current thread */
293 if (g_tasklist
[i
].addr
== rtos
->symbols
[0].address
)
294 rtos
->current_thread
= head
;
299 struct thread_detail
*thread
;
300 ret
= target_read_buffer(rtos
->target
, tcb_addr
,
301 sizeof(tcb
), (uint8_t *)&tcb
);
303 LOG_ERROR("target_read_buffer : ret = %d\n",
309 rtos
->thread_details
= realloc(rtos
->thread_details
,
310 sizeof(struct thread_detail
) * thread_count
);
311 thread
= &rtos
->thread_details
[thread_count
- 1];
312 thread
->threadid
= tcb_addr
;
313 thread
->exists
= true;
315 state
= tcb
.dat
[state_offset
- 8];
316 thread
->extra_info_str
= NULL
;
317 if (state
< ARRAY_SIZE(task_state_str
)) {
318 thread
->extra_info_str
= malloc(256);
319 snprintf(thread
->extra_info_str
, 256, "pid:%d, %s",
320 tcb
.dat
[pid_offset
- 8] |
321 tcb
.dat
[pid_offset
- 8 + 1] << 8,
322 task_state_str
[state
]);
326 thread
->thread_name_str
= malloc(name_size
+ 1);
327 snprintf(thread
->thread_name_str
, name_size
,
328 "%s", (char *)&tcb
.dat
[name_offset
- 8]);
330 thread
->thread_name_str
= malloc(sizeof("None"));
331 strcpy(thread
->thread_name_str
, "None");
334 tcb_addr
= tcb
.flink
;
337 rtos
->thread_count
= thread_count
;
344 * thread_id = tcb address;
346 static int nuttx_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
347 struct rtos_reg
**reg_list
, int *num_regs
)
351 /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */
352 bool cm4_fpu_enabled
= false;
353 struct armv7m_common
*armv7m_target
= target_to_armv7m(rtos
->target
);
354 if (is_armv7m(armv7m_target
)) {
355 if (armv7m_target
->fp_feature
== FPV4_SP
) {
356 /* Found ARM v7m target which includes a FPU */
359 retval
= target_read_u32(rtos
->target
, FPU_CPACR
, &cpacr
);
360 if (retval
!= ERROR_OK
) {
361 LOG_ERROR("Could not read CPACR register to check FPU state");
365 /* Check if CP10 and CP11 are set to full access. */
366 if (cpacr
& 0x00F00000) {
367 /* Found target with enabled FPU */
373 const struct rtos_register_stacking
*stacking
;
375 stacking
= &nuttx_stacking_cortex_m_fpu
;
377 stacking
= &nuttx_stacking_cortex_m
;
379 return rtos_generic_stack_read(rtos
->target
, stacking
,
380 (uint32_t)thread_id
+ xcpreg_offset
, reg_list
, num_regs
);
383 static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
387 *symbol_list
= (struct symbol_table_elem
*) calloc(1,
388 sizeof(struct symbol_table_elem
) * ARRAY_SIZE(nuttx_symbol_list
));
390 for (i
= 0; i
< ARRAY_SIZE(nuttx_symbol_list
); i
++)
391 (*symbol_list
)[i
].symbol_name
= nuttx_symbol_list
[i
];
396 struct rtos_type nuttx_rtos
= {
398 .detect_rtos
= nuttx_detect_rtos
,
399 .create
= nuttx_create
,
400 .update_threads
= nuttx_update_threads
,
401 .get_thread_reg_list
= nuttx_get_thread_reg_list
,
402 .get_symbol_list_to_lookup
= nuttx_get_symbol_list_to_lookup
,