build: cleanup src/rtos directory
[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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "rtos_standard_stackings.h"
32
33 #define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset)
34
35 struct FreeRTOS_params {
36 const char *target_name;
37 const unsigned char thread_count_width;
38 const unsigned char pointer_width;
39 const unsigned char list_next_offset;
40 const unsigned char list_width;
41 const unsigned char list_elem_next_offset;
42 const unsigned char list_elem_content_offset;
43 const unsigned char thread_stack_offset;
44 const unsigned char thread_name_offset;
45 const struct rtos_register_stacking *stacking_info;
46 };
47
48 const struct FreeRTOS_params FreeRTOS_params_list[] = {
49 {
50 "cortex_m3", /* target_name */
51 4, /* thread_count_width; */
52 4, /* pointer_width; */
53 16, /* list_next_offset; */
54 20, /* list_width; */
55 8, /* list_elem_next_offset; */
56 12, /* list_elem_content_offset */
57 0, /* thread_stack_offset; */
58 52, /* thread_name_offset; */
59 &rtos_standard_Cortex_M3_stacking, /* stacking_info */
60 }
61 };
62
63 #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
64
65 static int FreeRTOS_detect_rtos(struct target *target);
66 static int FreeRTOS_create(struct target *target);
67 static int FreeRTOS_update_threads(struct rtos *rtos);
68 static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
69 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
70
71 struct rtos_type FreeRTOS_rtos = {
72 .name = "FreeRTOS",
73
74 .detect_rtos = FreeRTOS_detect_rtos,
75 .create = FreeRTOS_create,
76 .update_threads = FreeRTOS_update_threads,
77 .get_thread_reg_list = FreeRTOS_get_thread_reg_list,
78 .get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup,
79 };
80
81 enum FreeRTOS_symbol_values {
82 FreeRTOS_VAL_pxCurrentTCB = 0,
83 FreeRTOS_VAL_pxReadyTasksLists = 1,
84 FreeRTOS_VAL_xDelayedTaskList1 = 2,
85 FreeRTOS_VAL_xDelayedTaskList2 = 3,
86 FreeRTOS_VAL_pxDelayedTaskList = 4,
87 FreeRTOS_VAL_pxOverflowDelayedTaskList = 5,
88 FreeRTOS_VAL_xPendingReadyList = 6,
89 FreeRTOS_VAL_xTasksWaitingTermination = 7,
90 FreeRTOS_VAL_xSuspendedTaskList = 8,
91 FreeRTOS_VAL_uxCurrentNumberOfTasks = 9,
92 FreeRTOS_VAL_uxTopUsedPriority = 10,
93 };
94
95 static char *FreeRTOS_symbol_list[] = {
96 "pxCurrentTCB",
97 "pxReadyTasksLists",
98 "xDelayedTaskList1",
99 "xDelayedTaskList2",
100 "pxDelayedTaskList",
101 "pxOverflowDelayedTaskList",
102 "xPendingReadyList",
103 "xTasksWaitingTermination",
104 "xSuspendedTaskList",
105 "uxCurrentNumberOfTasks",
106 "uxTopUsedPriority",
107 NULL
108 };
109
110 #define FREERTOS_NUM_SYMBOLS (sizeof(FreeRTOS_symbol_list)/sizeof(char *))
111
112 /* TODO: */
113 /* this is not safe for little endian yet */
114 /* may be problems reading if sizes are not 32 bit long integers. */
115 /* test mallocs for failure */
116
117 static int FreeRTOS_update_threads(struct rtos *rtos)
118 {
119 int i = 0;
120 int retval;
121 int tasks_found = 0;
122 const struct FreeRTOS_params *param;
123
124 if (rtos->rtos_specific_params == NULL)
125 return -1;
126
127 param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
128
129 if (rtos->symbols == NULL) {
130 LOG_OUTPUT("No symbols for FreeRTOS\r\n");
131 return -3;
132 }
133
134 if (rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0) {
135 LOG_OUTPUT("Don't have the number of threads in FreeRTOS \r\n");
136 return -2;
137 }
138
139 int thread_list_size = 0;
140 retval = target_read_buffer(rtos->target,
141 rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address,
142 param->thread_count_width,
143 (uint8_t *)&thread_list_size);
144
145 if (retval != ERROR_OK) {
146 LOG_OUTPUT("Could not read FreeRTOS thread count from target\r\n");
147 return retval;
148 }
149
150 /* wipe out previous thread details if any */
151 if (rtos->thread_details != NULL) {
152 int j;
153 for (j = 0; j < rtos->thread_count; j++) {
154 if (rtos->thread_details[j].display_str != NULL) {
155 free(rtos->thread_details[j].display_str);
156 rtos->thread_details[j].display_str = NULL;
157 }
158 if (rtos->thread_details[j].thread_name_str != NULL) {
159 free(rtos->thread_details[j].thread_name_str);
160 rtos->thread_details[j].thread_name_str = NULL;
161 }
162 if (rtos->thread_details[j].extra_info_str != NULL) {
163 free(rtos->thread_details[j].extra_info_str);
164 rtos->thread_details[j].extra_info_str = NULL;
165 }
166 }
167 free(rtos->thread_details);
168 rtos->thread_details = NULL;
169 }
170
171 /* read the current thread */
172 retval = target_read_buffer(rtos->target,
173 rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address,
174 param->pointer_width,
175 (uint8_t *)&rtos->current_thread);
176 if (retval != ERROR_OK) {
177 LOG_OUTPUT("Error reading current thread in FreeRTOS thread list\r\n");
178 return retval;
179 }
180
181 if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
182 /* Either : No RTOS threads - there is always at least the current execution though */
183 /* OR : No current thread - all threads suspended - show the current execution
184 * of idling */
185 char tmp_str[] = "Current Execution";
186 thread_list_size++;
187 tasks_found++;
188 rtos->thread_details = (struct thread_detail *) malloc(
189 sizeof(struct thread_detail) * thread_list_size);
190 rtos->thread_details->threadid = 1;
191 rtos->thread_details->exists = true;
192 rtos->thread_details->display_str = NULL;
193 rtos->thread_details->extra_info_str = NULL;
194 rtos->thread_details->thread_name_str = (char *) malloc(sizeof(tmp_str));
195 strcpy(rtos->thread_details->thread_name_str, tmp_str);
196
197 if (thread_list_size == 1) {
198 rtos->thread_count = 1;
199 return ERROR_OK;
200 }
201 } else {
202 /* create space for new thread details */
203 rtos->thread_details = (struct thread_detail *) malloc(
204 sizeof(struct thread_detail) * thread_list_size);
205 }
206
207 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
208 int64_t max_used_priority = 0;
209 retval = target_read_buffer(rtos->target,
210 rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address,
211 param->pointer_width,
212 (uint8_t *)&max_used_priority);
213 if (retval != ERROR_OK)
214 return retval;
215
216 symbol_address_t *list_of_lists =
217 (symbol_address_t *)malloc(sizeof(symbol_address_t) *
218 (max_used_priority+1 + 5));
219
220 int num_lists;
221 for (num_lists = 0; num_lists <= max_used_priority; num_lists++)
222 list_of_lists[num_lists] = rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address +
223 num_lists * param->list_width;
224
225 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList1].address;
226 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList2].address;
227 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xPendingReadyList].address;
228 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xSuspendedTaskList].address;
229 list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address;
230
231 for (i = 0; i < num_lists; i++) {
232 if (list_of_lists[i] == 0)
233 continue;
234
235 /* Read the number of threads in this list */
236 int64_t list_thread_count = 0;
237 retval = target_read_buffer(rtos->target,
238 list_of_lists[i],
239 param->thread_count_width,
240 (uint8_t *)&list_thread_count);
241 if (retval != ERROR_OK) {
242 LOG_OUTPUT("Error reading number of threads in FreeRTOS thread list\r\n");
243 return retval;
244 }
245
246 if (list_thread_count == 0)
247 continue;
248
249 /* Read the location of first list item */
250 uint64_t prev_list_elem_ptr = -1;
251 uint64_t list_elem_ptr = 0;
252 retval = target_read_buffer(rtos->target,
253 list_of_lists[i] + param->list_next_offset,
254 param->pointer_width,
255 (uint8_t *)&list_elem_ptr);
256 if (retval != ERROR_OK) {
257 LOG_OUTPUT(
258 "Error reading first thread item location in FreeRTOS thread list\r\n");
259 return retval;
260 }
261
262 while ((list_thread_count > 0) && (list_elem_ptr != 0) &&
263 (list_elem_ptr != prev_list_elem_ptr) &&
264 (tasks_found < thread_list_size)) {
265 /* Get the location of the thread structure. */
266 rtos->thread_details[tasks_found].threadid = 0;
267 retval = target_read_buffer(rtos->target,
268 list_elem_ptr + param->list_elem_content_offset,
269 param->pointer_width,
270 (uint8_t *)&(rtos->thread_details[tasks_found].threadid));
271 if (retval != ERROR_OK) {
272 LOG_OUTPUT(
273 "Error reading thread list item object in FreeRTOS thread list\r\n");
274 return retval;
275 }
276
277 /* get thread name */
278
279 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
280 char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
281
282 /* Read the thread name */
283 retval = target_read_buffer(rtos->target,
284 rtos->thread_details[tasks_found].threadid + param->thread_name_offset,
285 FREERTOS_THREAD_NAME_STR_SIZE,
286 (uint8_t *)&tmp_str);
287 if (retval != ERROR_OK) {
288 LOG_OUTPUT(
289 "Error reading first thread item location in FreeRTOS thread list\r\n");
290 return retval;
291 }
292 tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
293
294 if (tmp_str[0] == '\x00')
295 strcpy(tmp_str, "No Name");
296
297 rtos->thread_details[tasks_found].thread_name_str =
298 (char *)malloc(strlen(tmp_str)+1);
299 strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
300 rtos->thread_details[tasks_found].display_str = NULL;
301 rtos->thread_details[tasks_found].exists = true;
302
303 if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) {
304 char running_str[] = "Running";
305 rtos->thread_details[tasks_found].extra_info_str = (char *) malloc(
306 sizeof(running_str));
307 strcpy(rtos->thread_details[tasks_found].extra_info_str,
308 running_str);
309 } else
310 rtos->thread_details[tasks_found].extra_info_str = NULL;
311
312 tasks_found++;
313 list_thread_count--;
314
315 prev_list_elem_ptr = list_elem_ptr;
316 list_elem_ptr = 0;
317 retval = target_read_buffer(rtos->target,
318 prev_list_elem_ptr + param->list_elem_next_offset,
319 param->pointer_width,
320 (uint8_t *)&list_elem_ptr);
321 if (retval != ERROR_OK) {
322 LOG_OUTPUT(
323 "Error reading next thread item location in FreeRTOS thread list\r\n");
324 return retval;
325 }
326 }
327 }
328 free(list_of_lists);
329 rtos->thread_count = tasks_found;
330 return 0;
331 }
332
333 static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
334 {
335 int retval;
336 const struct FreeRTOS_params *param;
337 int64_t stack_ptr = 0;
338
339 *hex_reg_list = NULL;
340 if (rtos == NULL)
341 return -1;
342
343 if (thread_id == 0)
344 return -2;
345
346 if (rtos->rtos_specific_params == NULL)
347 return -1;
348
349 param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
350
351 /* Read the stack pointer */
352 retval = target_read_buffer(rtos->target,
353 thread_id + param->thread_stack_offset,
354 param->pointer_width,
355 (uint8_t *)&stack_ptr);
356 if (retval != ERROR_OK) {
357 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
358 return retval;
359 }
360
361 return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list);
362
363 }
364
365 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
366 {
367 unsigned int i;
368 *symbol_list = (symbol_table_elem_t *) malloc(
369 sizeof(symbol_table_elem_t) * FREERTOS_NUM_SYMBOLS);
370
371 for (i = 0; i < FREERTOS_NUM_SYMBOLS; i++)
372 (*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i];
373
374 return 0;
375 }
376
377 #if 0
378
379 static int FreeRTOS_set_current_thread(struct rtos *rtos, threadid_t thread_id)
380 {
381 return 0;
382 }
383
384 static int FreeRTOS_get_thread_ascii_info(struct rtos *rtos, threadid_t thread_id, char **info)
385 {
386 int retval;
387 const struct FreeRTOS_params *param;
388
389 if (rtos == NULL)
390 return -1;
391
392 if (thread_id == 0)
393 return -2;
394
395 if (rtos->rtos_specific_params == NULL)
396 return -3;
397
398 param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
399
400 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
401 char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
402
403 /* Read the thread name */
404 retval = target_read_buffer(rtos->target,
405 thread_id + param->thread_name_offset,
406 FREERTOS_THREAD_NAME_STR_SIZE,
407 (uint8_t *)&tmp_str);
408 if (retval != ERROR_OK) {
409 LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
410 return retval;
411 }
412 tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
413
414 if (tmp_str[0] == '\x00')
415 strcpy(tmp_str, "No Name");
416
417 *info = (char *)malloc(strlen(tmp_str)+1);
418 strcpy(*info, tmp_str);
419 return 0;
420 }
421
422 #endif
423
424 static int FreeRTOS_detect_rtos(struct target *target)
425 {
426 if ((target->rtos->symbols != NULL) &&
427 (target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0)) {
428 /* looks like FreeRTOS */
429 return 1;
430 }
431 return 0;
432 }
433
434 static int FreeRTOS_create(struct target *target)
435 {
436 int i = 0;
437 while ((i < FREERTOS_NUM_PARAMS) &&
438 (0 != strcmp(FreeRTOS_params_list[i].target_name, target->type->name))) {
439 i++;
440 }
441 if (i >= FREERTOS_NUM_PARAMS) {
442 LOG_OUTPUT("Could not find target in FreeRTOS compatibility list\r\n");
443 return -1;
444 }
445
446 target->rtos->rtos_specific_params = (void *) &FreeRTOS_params_list[i];
447 return 0;
448 }

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)