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
,