Don't cast return value of [cm]alloc
[openocd.git] / src / rtos / FreeRTOS.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Broadcom Corporation *
3 * Evan Hunter - ehunter@broadcom.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <helper/time_support.h>
26 #include <jtag/jtag.h>
27 #include "target/target.h"
28 #include "target/target_type.h"
29 #include "rtos.h"
30 #include "helper/log.h"
31 #include "helper/types.h"
32 #include "rtos_standard_stackings.h"
33
34 #define FREERTOS_MAX_PRIORITIES 63
35
36 #define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset)
37
38 struct FreeRTOS_params {
39 const char *target_name;
40 const unsigned char thread_count_width;
41 const unsigned char pointer_width;
42 const unsigned char list_next_offset;
43 const unsigned char list_width;
44 const unsigned char list_elem_next_offset;
45 const unsigned char list_elem_content_offset;
46 const unsigned char thread_stack_offset;
47 const unsigned char thread_name_offset;
48 const struct rtos_register_stacking *stacking_info;
49 };
50
51 const struct FreeRTOS_params FreeRTOS_params_list[] = {
52 {
53 "cortex_m", /* target_name */
54 4, /* thread_count_width; */
55 4, /* pointer_width; */
56 16, /* list_next_offset; */
57 20, /* list_width; */
58 8, /* list_elem_next_offset; */
59 12, /* list_elem_content_offset */
60 0, /* thread_stack_offset; */
61 52, /* thread_name_offset; */
62 &rtos_standard_Cortex_M3_stacking, /* stacking_info */
63 },
64 {
65 "hla_target", /* target_name */
66 4, /* thread_count_width; */
67 4, /* pointer_width; */
68 16, /* list_next_offset; */
69 20, /* list_width; */
70 8, /* list_elem_next_offset; */
71 12, /* list_elem_content_offset */
72 0, /* thread_stack_offset; */
73 52, /* thread_name_offset; */
74 &rtos_standard_Cortex_M3_stacking, /* stacking_info */
75 },
76 {
77 "nds32_v3", /* target_name */
78 4, /* thread_count_width; */
79 4, /* pointer_width; */
80 16, /* list_next_offset; */
81 20, /* list_width; */
82 8, /* list_elem_next_offset; */
83 12, /* list_elem_content_offset */
84 0, /* thread_stack_offset; */
85 52, /* thread_name_offset; */
86 &rtos_standard_NDS32_N1068_stacking, /* stacking_info */
87 },
88 };
89
90 #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
91
92 static int FreeRTOS_detect_rtos(struct target *target);
93 static int FreeRTOS_create(struct target *target);
94 static int FreeRTOS_update_threads(struct rtos *rtos);
95 static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
96 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
97
98 struct rtos_type FreeRTOS_rtos = {
99 .name = "FreeRTOS",
100
101 .detect_rtos = FreeRTOS_detect_rtos,
102 .create = FreeRTOS_create,
103 .update_threads = FreeRTOS_update_threads,
104 .get_thread_reg_list = FreeRTOS_get_thread_reg_list,
105 .get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup,
106 };
107
108 enum FreeRTOS_symbol_values {
109 FreeRTOS_VAL_pxCurrentTCB = 0,
110 FreeRTOS_VAL_pxReadyTasksLists = 1,
111 FreeRTOS_VAL_xDelayedTaskList1 = 2,
112 FreeRTOS_VAL_xDelayedTaskList2 = 3,
113 FreeRTOS_VAL_pxDelayedTaskList = 4,
114 FreeRTOS_VAL_pxOverflowDelayedTaskList = 5,
115 FreeRTOS_VAL_xPendingReadyList = 6,
116 FreeRTOS_VAL_xTasksWaitingTermination = 7,
117 FreeRTOS_VAL_xSuspendedTaskList = 8,
118 FreeRTOS_VAL_uxCurrentNumberOfTasks = 9,
119 FreeRTOS_VAL_uxTopUsedPriority = 10,
120 };
121
122 static char *FreeRTOS_symbol_list[] = {
123 "pxCurrentTCB",
124 "pxReadyTasksLists",
125 "xDelayedTaskList1",
126 "xDelayedTaskList2",
127 "pxDelayedTaskList",
128 "pxOverflowDelayedTaskList",
129 "xPendingReadyList",
130 "xTasksWaitingTermination",
131 "xSuspendedTaskList",
132 "uxCurrentNumberOfTasks",
133 "uxTopUsedPriority",
134 NULL
135 };
136
137 /* TODO: */
138 /* this is not safe for little endian yet */
139 /* may be problems reading if sizes are not 32 bit long integers. */
140 /* test mallocs for failure */
141
142 static int FreeRTOS_update_threads(struct rtos *rtos)
143 {
144 int i = 0;
145 int retval;
146 int tasks_found = 0;
147 const struct FreeRTOS_params *param;
148
149 if (rtos->rtos_specific_params == NULL)
150 return -1;
151
152 param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
153
154 if (rtos->symbols == NULL) {
155 LOG_ERROR("No symbols for FreeRTOS");
156 return -3;
157 }
158
159 if (rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0) {
160 LOG_ERROR("Don't have the number of threads in FreeRTOS");
161 return -2;
162 }
163
164 int thread_list_size = 0;
165 retval = target_read_buffer(rtos->target,
166 rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address,
167 param->thread_count_width,
168 (uint8_t *)&thread_list_size);
169
170 if (retval != ERROR_OK) {
171 LOG_ERROR("Could not read FreeRTOS thread count from target");
172 return retval;
173 }
174
175 /* wipe out previous thread details if any */
176 rtos_free_threadlist(rtos);
177
178 /* read the current thread */
179 retval = target_read_buffer(rtos->target,
180 rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address,
181 param->pointer_width,
182 (uint8_t *)&rtos->current_thread);
183 if (retval != ERROR_OK) {
184 LOG_ERROR("Error reading current thread in FreeRTOS thread list");
185 return retval;
186 }
187
188 if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
189 /* Either : No RTOS threads - there is always at least the current execution though */
190 /* OR : No current thread - all threads suspended - show the current execution
191 * of idling */
192 char tmp_str[] = "Current Execution";
193 thread_list_size++;
194 tasks_found++;
195 rtos->thread_details = malloc(
196 sizeof(struct thread_detail) * thread_list_size);
197 if (!rtos->thread_details) {
198 LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
199 return ERROR_FAIL;
200 }
201 rtos->thread_details->threadid = 1;
202 rtos->thread_details->exists = true;
203 rtos->thread_details->display_str = NULL;
204 rtos->thread_details->extra_info_str = NULL;
205 rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
206 strcpy(rtos->thread_details->thread_name_str, tmp_str);
207
208 if (thread_list_size == 1) {
209 rtos->thread_count = 1;
210 return ERROR_OK;
211 }
212 } else {
213 /* create space for new thread details */
214 rtos->thread_details = malloc(
215 sizeof(struct thread_detail) * thread_list_size);
216 if (!rtos->thread_details) {
217 LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
218 return ERROR_FAIL;
219 }
220 }
221
222 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
223 int64_t max_used_priority = 0;
224 retval = target_read_buffer(rtos->target,
225 rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address,
226 param->pointer_width,
227 (uint8_t *)&max_used_priority);
228 if (retval != ERROR_OK)
229 return retval;
230 if (max_used_priority > FREERTOS_MAX_PRIORITIES) {
231 LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64 "",
232 max_used_priority);
233 return ERROR_FAIL;
234 }
235
236 symbol_address_t *list_of_lists =
237 malloc(sizeof(symbol_address_t) *
238 (max_used_priority+1 + 5));
239 if (!list_of_lists) {
240 LOG_ERROR("Error allocating memory for %" PRId64 " priorities", max_used_priority);
241 return ERROR_FAIL;
242 }
243
244 int num_lists;
245 for (num_lists = 0; num_lists <= max_used_priority; num_lists++)
246 list_of_lists[num_lists] = rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address +
247 num_lists * param->list_width;
248
249 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList1].address;
250 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList2].address;
251 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xPendingReadyList].address;
252 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xSuspendedTaskList].address;
253 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address;
254
255 for (i = 0; i < num_lists; i++) {
256 if (list_of_lists[i] == 0)
257 continue;
258
259 /* Read the number of threads in this list */
260 int64_t list_thread_count = 0;
261 retval = target_read_buffer(rtos->target,
262 list_of_lists[i],
263 param->thread_count_width,
264 (uint8_t *)&list_thread_count);
265 if (retval != ERROR_OK) {
266 LOG_ERROR("Error reading number of threads in FreeRTOS thread list");
267 free(list_of_lists);
268 return retval;
269 }
270
271 if (list_thread_count == 0)
272 continue;
273
274 /* Read the location of first list item */
275 uint64_t prev_list_elem_ptr = -1;
276 uint64_t list_elem_ptr = 0;
277 retval = target_read_buffer(rtos->target,
278 list_of_lists[i] + param->list_next_offset,
279 param->pointer_width,
280 (uint8_t *)&list_elem_ptr);
281 if (retval != ERROR_OK) {
282 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
283 free(list_of_lists);
284 return retval;
285 }
286
287 while ((list_thread_count > 0) && (list_elem_ptr != 0) &&
288 (list_elem_ptr != prev_list_elem_ptr) &&
289 (tasks_found < thread_list_size)) {
290 /* Get the location of the thread structure. */
291 rtos->thread_details[tasks_found].threadid = 0;
292 retval = target_read_buffer(rtos->target,
293 list_elem_ptr + param->list_elem_content_offset,
294 param->pointer_width,
295 (uint8_t *)&(rtos->thread_details[tasks_found].threadid));
296 if (retval != ERROR_OK) {
297 LOG_ERROR("Error reading thread list item object in FreeRTOS thread list");
298 free(list_of_lists);
299 return retval;
300 }
301
302 /* get thread name */
303
304 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
305 char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
306
307 /* Read the thread name */
308 retval = target_read_buffer(rtos->target,
309 rtos->thread_details[tasks_found].threadid + param->thread_name_offset,
310 FREERTOS_THREAD_NAME_STR_SIZE,
311 (uint8_t *)&tmp_str);
312 if (retval != ERROR_OK) {
313 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
314 free(list_of_lists);
315 return retval;
316 }
317 tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
318
319 if (tmp_str[0] == '\x00')
320 strcpy(tmp_str, "No Name");
321
322 rtos->thread_details[tasks_found].thread_name_str =
323 malloc(strlen(tmp_str)+1);
324 strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
325 rtos->thread_details[tasks_found].display_str = NULL;
326 rtos->thread_details[tasks_found].exists = true;
327
328 if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) {
329 char running_str[] = "Running";
330 rtos->thread_details[tasks_found].extra_info_str = malloc(
331 sizeof(running_str));
332 strcpy(rtos->thread_details[tasks_found].extra_info_str,
333 running_str);
334 } else
335 rtos->thread_details[tasks_found].extra_info_str = NULL;
336
337 tasks_found++;
338 list_thread_count--;
339
340 prev_list_elem_ptr = list_elem_ptr;
341 list_elem_ptr = 0;
342 retval = target_read_buffer(rtos->target,
343 prev_list_elem_ptr + param->list_elem_next_offset,
344 param->pointer_width,
345 (uint8_t *)&list_elem_ptr);
346 if (retval != ERROR_OK) {
347 LOG_ERROR("Error reading next thread item location in FreeRTOS thread list");
348 free(list_of_lists);
349 return retval;
350 }
351 }
352 }
353
354 free(list_of_lists);
355 rtos->thread_count = tasks_found;
356 return 0;
357 }
358
359 static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
360 {
361 int retval;
362 const struct FreeRTOS_params *param;
363 int64_t stack_ptr = 0;
364
365 *hex_reg_list = NULL;
366 if (rtos == NULL)
367 return -1;
368
369 if (thread_id == 0)
370 return -2;
371
372 if (rtos->rtos_specific_params == NULL)
373 return -1;
374
375 param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
376
377 /* Read the stack pointer */
378 retval = target_read_buffer(rtos->target,
379 thread_id + param->thread_stack_offset,
380 param->pointer_width,
381 (uint8_t *)&stack_ptr);
382 if (retval != ERROR_OK) {
383 LOG_ERROR("Error reading stack frame from FreeRTOS thread");
384 return retval;
385 }
386
387 return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list);
388 }
389
390 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
391 {
392 unsigned int i;
393 *symbol_list = malloc(
394 sizeof(symbol_table_elem_t) * ARRAY_SIZE(FreeRTOS_symbol_list));
395
396 for (i = 0; i < ARRAY_SIZE(FreeRTOS_symbol_list); i++)
397 (*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i];
398
399 return 0;
400 }
401
402 #if 0
403
404 static int FreeRTOS_set_current_thread(struct rtos *rtos, threadid_t thread_id)
405 {
406 return 0;
407 }
408
409 static int FreeRTOS_get_thread_ascii_info(struct rtos *rtos, threadid_t thread_id, char **info)
410 {
411 int retval;
412 const struct FreeRTOS_params *param;
413
414 if (rtos == NULL)
415 return -1;
416
417 if (thread_id == 0)
418 return -2;
419
420 if (rtos->rtos_specific_params == NULL)
421 return -3;
422
423 param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
424
425 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
426 char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
427
428 /* Read the thread name */
429 retval = target_read_buffer(rtos->target,
430 thread_id + param->thread_name_offset,
431 FREERTOS_THREAD_NAME_STR_SIZE,
432 (uint8_t *)&tmp_str);
433 if (retval != ERROR_OK) {
434 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
435 return retval;
436 }
437 tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
438
439 if (tmp_str[0] == '\x00')
440 strcpy(tmp_str, "No Name");
441
442 *info = malloc(strlen(tmp_str)+1);
443 strcpy(*info, tmp_str);
444 return 0;
445 }
446
447 #endif
448
449 static int FreeRTOS_detect_rtos(struct target *target)
450 {
451 if ((target->rtos->symbols != NULL) &&
452 (target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0)) {
453 /* looks like FreeRTOS */
454 return 1;
455 }
456 return 0;
457 }
458
459 static int FreeRTOS_create(struct target *target)
460 {
461 int i = 0;
462 while ((i < FREERTOS_NUM_PARAMS) &&
463 (0 != strcmp(FreeRTOS_params_list[i].target_name, target->type->name))) {
464 i++;
465 }
466 if (i >= FREERTOS_NUM_PARAMS) {
467 LOG_ERROR("Could not find target in FreeRTOS compatibility list");
468 return -1;
469 }
470
471 target->rtos->rtos_specific_params = (void *) &FreeRTOS_params_list[i];
472 return 0;
473 }

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)