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,