jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / rtos / nuttx.c
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 *
5 * *
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. *
10 * *
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. *
15 * *
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 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
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"
29 #include "rtos.h"
30 #include "helper/log.h"
31 #include "helper/types.h"
32 #include "server/gdb_server.h"
33
34 #include "nuttx_header.h"
35
36
37 int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
38
39 #ifdef CONFIG_DISABLE_SIGNALS
40 #define SIG_QUEUE_NUM 0
41 #else
42 #define SIG_QUEUE_NUM 1
43 #endif /* CONFIG_DISABLE_SIGNALS */
44
45 #ifdef CONFIG_DISABLE_MQUEUE
46 #define M_QUEUE_NUM 0
47 #else
48 #define M_QUEUE_NUM 2
49 #endif /* CONFIG_DISABLE_MQUEUE */
50
51 #ifdef CONFIG_PAGING
52 #define PAGING_QUEUE_NUM 1
53 #else
54 #define PAGING_QUEUE_NUM 0
55 #endif /* CONFIG_PAGING */
56
57
58 #define TASK_QUEUE_NUM (6 + SIG_QUEUE_NUM + M_QUEUE_NUM + PAGING_QUEUE_NUM)
59
60
61 /* see nuttx/sched/os_start.c */
62 static char *nuttx_symbol_list[] = {
63 "g_readytorun", /* 0: must be top of this array */
64 "g_tasklisttable",
65 NULL
66 };
67
68 /* see nuttx/include/nuttx/sched.h */
69 struct tcb {
70 uint32_t flink;
71 uint32_t blink;
72 uint8_t dat[512];
73 };
74
75 static struct {
76 uint32_t addr;
77 uint32_t prio;
78 } g_tasklist[TASK_QUEUE_NUM];
79
80 static char *task_state_str[] = {
81 "INVALID",
82 "PENDING",
83 "READYTORUN",
84 "RUNNING",
85 "INACTIVE",
86 "WAIT_SEM",
87 #ifndef CONFIG_DISABLE_SIGNALS
88 "WAIT_SIG",
89 #endif /* CONFIG_DISABLE_SIGNALS */
90 #ifndef CONFIG_DISABLE_MQUEUE
91 "WAIT_MQNOTEMPTY",
92 "WAIT_MQNOTFULL",
93 #endif /* CONFIG_DISABLE_MQUEUE */
94 #ifdef CONFIG_PAGING
95 "WAIT_PAGEFILL",
96 #endif /* CONFIG_PAGING */
97 };
98
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 */
118 };
119
120
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
126 };
127
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 */
146 };
147
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
153 };
154
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;
160
161 static int rcmd_offset(const char *cmd, const char *name)
162 {
163 if (strncmp(cmd, name, strlen(name)))
164 return -1;
165
166 if (strlen(cmd) <= strlen(name) + 1)
167 return -1;
168
169 return atoi(cmd + strlen(name));
170 }
171
172 static int nuttx_thread_packet(struct connection *connection,
173 char const *packet, int packet_size)
174 {
175 char cmd[GDB_BUFFER_SIZE / 2 + 1] = ""; /* Extra byte for null-termination */
176
177 if (!strncmp(packet, "qRcmd", 5)) {
178 size_t len = unhexify((uint8_t *)cmd, packet + 6, sizeof(cmd));
179 int offset;
180
181 if (len <= 0)
182 goto pass;
183
184 offset = rcmd_offset(cmd, "nuttx.pid_offset");
185
186 if (offset >= 0) {
187 LOG_INFO("pid_offset: %d", offset);
188 pid_offset = offset;
189 goto retok;
190 }
191
192 offset = rcmd_offset(cmd, "nuttx.state_offset");
193
194 if (offset >= 0) {
195 LOG_INFO("state_offset: %d", offset);
196 state_offset = offset;
197 goto retok;
198 }
199
200 offset = rcmd_offset(cmd, "nuttx.name_offset");
201
202 if (offset >= 0) {
203 LOG_INFO("name_offset: %d", offset);
204 name_offset = offset;
205 goto retok;
206 }
207
208 offset = rcmd_offset(cmd, "nuttx.xcpreg_offset");
209
210 if (offset >= 0) {
211 LOG_INFO("xcpreg_offset: %d", offset);
212 xcpreg_offset = offset;
213 goto retok;
214 }
215
216 offset = rcmd_offset(cmd, "nuttx.name_size");
217
218 if (offset >= 0) {
219 LOG_INFO("name_size: %d", offset);
220 name_size = offset;
221 goto retok;
222 }
223 }
224 pass:
225 return rtos_thread_packet(connection, packet, packet_size);
226 retok:
227 gdb_put_packet(connection, "OK", 2);
228 return ERROR_OK;
229 }
230
231
232 static bool nuttx_detect_rtos(struct target *target)
233 {
234 if ((target->rtos->symbols) &&
235 (target->rtos->symbols[0].address != 0) &&
236 (target->rtos->symbols[1].address != 0)) {
237 return true;
238 }
239 return false;
240 }
241
242 static int nuttx_create(struct target *target)
243 {
244
245 target->rtos->gdb_thread_packet = nuttx_thread_packet;
246 LOG_INFO("target type name = %s", target->type->name);
247 return 0;
248 }
249
250 static int nuttx_update_threads(struct rtos *rtos)
251 {
252 uint32_t thread_count;
253 struct tcb tcb;
254 int ret;
255 uint32_t head;
256 uint32_t tcb_addr;
257 uint32_t i;
258 uint8_t state;
259
260 if (!rtos->symbols) {
261 LOG_ERROR("No symbols for NuttX");
262 return -3;
263 }
264
265 /* free previous thread details */
266 rtos_free_threadlist(rtos);
267
268 ret = target_read_buffer(rtos->target, rtos->symbols[1].address,
269 sizeof(g_tasklist), (uint8_t *)&g_tasklist);
270 if (ret) {
271 LOG_ERROR("target_read_buffer : ret = %d\n", ret);
272 return ERROR_FAIL;
273 }
274
275 thread_count = 0;
276
277 for (i = 0; i < TASK_QUEUE_NUM; i++) {
278
279 if (g_tasklist[i].addr == 0)
280 continue;
281
282 ret = target_read_u32(rtos->target, g_tasklist[i].addr,
283 &head);
284
285 if (ret) {
286 LOG_ERROR("target_read_u32 : ret = %d\n", ret);
287 return ERROR_FAIL;
288 }
289
290 /* readytorun head is current thread */
291 if (g_tasklist[i].addr == rtos->symbols[0].address)
292 rtos->current_thread = head;
293
294
295 tcb_addr = head;
296 while (tcb_addr) {
297 struct thread_detail *thread;
298 ret = target_read_buffer(rtos->target, tcb_addr,
299 sizeof(tcb), (uint8_t *)&tcb);
300 if (ret) {
301 LOG_ERROR("target_read_buffer : ret = %d\n",
302 ret);
303 return ERROR_FAIL;
304 }
305 thread_count++;
306
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;
312
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]);
321 }
322
323 if (name_offset) {
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]);
327 } else {
328 thread->thread_name_str = malloc(sizeof("None"));
329 strcpy(thread->thread_name_str, "None");
330 }
331
332 tcb_addr = tcb.flink;
333 }
334 }
335 rtos->thread_count = thread_count;
336
337 return 0;
338 }
339
340
341 /*
342 * thread_id = tcb address;
343 */
344 static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
345 struct rtos_reg **reg_list, int *num_regs)
346 {
347 int retval;
348
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 */
355 uint32_t cpacr;
356
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");
360 return -1;
361 }
362
363 /* Check if CP10 and CP11 are set to full access. */
364 if (cpacr & 0x00F00000) {
365 /* Found target with enabled FPU */
366 cm4_fpu_enabled = 1;
367 }
368 }
369 }
370
371 const struct rtos_register_stacking *stacking;
372 if (cm4_fpu_enabled)
373 stacking = &nuttx_stacking_cortex_m_fpu;
374 else
375 stacking = &nuttx_stacking_cortex_m;
376
377 return rtos_generic_stack_read(rtos->target, stacking,
378 (uint32_t)thread_id + xcpreg_offset, reg_list, num_regs);
379 }
380
381 static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
382 {
383 unsigned int i;
384
385 *symbol_list = (struct symbol_table_elem *) calloc(1,
386 sizeof(struct symbol_table_elem) * ARRAY_SIZE(nuttx_symbol_list));
387
388 for (i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++)
389 (*symbol_list)[i].symbol_name = nuttx_symbol_list[i];
390
391 return 0;
392 }
393
394 struct rtos_type nuttx_rtos = {
395 .name = "nuttx",
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,
401 };

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)