target: remove unused function target_buffer_get_u8()
[openocd.git] / src / rtos / embKernel.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, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <helper/time_support.h>
24 #include <jtag/jtag.h>
25 #include "target/target.h"
26 #include "target/target_type.h"
27 #include "rtos.h"
28 #include "helper/log.h"
29 #include "helper/types.h"
30 #include "rtos_embkernel_stackings.h"
31
32 #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
33
34 static bool embKernel_detect_rtos(struct target *target);
35 static int embKernel_create(struct target *target);
36 static int embKernel_update_threads(struct rtos *rtos);
37 static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
38 struct rtos_reg **reg_list, int *num_regs);
39 static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
40
41 struct rtos_type embKernel_rtos = {
42 .name = "embKernel",
43 .detect_rtos = embKernel_detect_rtos,
44 .create = embKernel_create,
45 .update_threads = embKernel_update_threads,
46 .get_thread_reg_list =
47 embKernel_get_thread_reg_list,
48 .get_symbol_list_to_lookup = embKernel_get_symbol_list_to_lookup,
49 };
50
51 enum {
52 SYMBOL_ID_sCurrentTask = 0,
53 SYMBOL_ID_sListReady = 1,
54 SYMBOL_ID_sListSleep = 2,
55 SYMBOL_ID_sListSuspended = 3,
56 SYMBOL_ID_sMaxPriorities = 4,
57 SYMBOL_ID_sCurrentTaskCount = 5,
58 };
59
60 static const char * const embKernel_symbol_list[] = {
61 "Rtos::sCurrentTask",
62 "Rtos::sListReady",
63 "Rtos::sListSleep",
64 "Rtos::sListSuspended",
65 "Rtos::sMaxPriorities",
66 "Rtos::sCurrentTaskCount",
67 NULL };
68
69 struct embKernel_params {
70 const char *target_name;
71 const unsigned char pointer_width;
72 const unsigned char thread_count_width;
73 const unsigned char rtos_list_size;
74 const unsigned char thread_stack_offset;
75 const unsigned char thread_name_offset;
76 const unsigned char thread_priority_offset;
77 const unsigned char thread_priority_width;
78 const unsigned char iterable_next_offset;
79 const unsigned char iterable_task_owner_offset;
80 const struct rtos_register_stacking *stacking_info;
81 };
82
83 static const struct embKernel_params embKernel_params_list[] = {
84 {
85 "cortex_m", /* target_name */
86 4, /* pointer_width */
87 4, /* thread_count_width */
88 8, /*rtos_list_size */
89 0, /*thread_stack_offset */
90 4, /*thread_name_offset */
91 8, /*thread_priority_offset */
92 4, /*thread_priority_width */
93 4, /*iterable_next_offset */
94 12, /*iterable_task_owner_offset */
95 &rtos_embkernel_Cortex_M_stacking, /* stacking_info*/
96 },
97 { "hla_target", /* target_name */
98 4, /* pointer_width */
99 4, /* thread_count_width */
100 8, /*rtos_list_size */
101 0, /*thread_stack_offset */
102 4, /*thread_name_offset */
103 8, /*thread_priority_offset */
104 4, /*thread_priority_width */
105 4, /*iterable_next_offset */
106 12, /*iterable_task_owner_offset */
107 &rtos_embkernel_Cortex_M_stacking, /* stacking_info */
108 }
109 };
110
111 static bool embKernel_detect_rtos(struct target *target)
112 {
113 if (target->rtos->symbols != NULL) {
114 if (target->rtos->symbols[SYMBOL_ID_sCurrentTask].address != 0)
115 return true;
116 }
117 return false;
118 }
119
120 static int embKernel_create(struct target *target)
121 {
122 size_t i = 0;
123 while ((i < ARRAY_SIZE(embKernel_params_list)) &&
124 (0 != strcmp(embKernel_params_list[i].target_name, target->type->name)))
125 i++;
126
127 if (i >= ARRAY_SIZE(embKernel_params_list)) {
128 LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
129 "list", target->type->name);
130 return -1;
131 }
132
133 target->rtos->rtos_specific_params = (void *) &embKernel_params_list[i];
134 return 0;
135 }
136
137 static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embKernel_params *param,
138 struct thread_detail *details, const char* state_str)
139 {
140 int64_t task = 0;
141 int retval = target_read_buffer(rtos->target, iterable + param->iterable_task_owner_offset, param->pointer_width,
142 (uint8_t *) &task);
143 if (retval != ERROR_OK)
144 return retval;
145 details->threadid = (threadid_t) task;
146 details->exists = true;
147
148 int64_t name_ptr = 0;
149 retval = target_read_buffer(rtos->target, task + param->thread_name_offset, param->pointer_width,
150 (uint8_t *) &name_ptr);
151 if (retval != ERROR_OK)
152 return retval;
153
154 details->thread_name_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
155 if (name_ptr) {
156 retval = target_read_buffer(rtos->target, name_ptr, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE,
157 (uint8_t *) details->thread_name_str);
158 if (retval != ERROR_OK)
159 return retval;
160 details->thread_name_str[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE - 1] = 0;
161 } else {
162 snprintf(details->thread_name_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "NoName:[0x%08X]", (unsigned int) task);
163 }
164
165 int64_t priority = 0;
166 retval = target_read_buffer(rtos->target, task + param->thread_priority_offset, param->thread_priority_width,
167 (uint8_t *) &priority);
168 if (retval != ERROR_OK)
169 return retval;
170 details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
171 if (task == rtos->current_thread) {
172 snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: Running, Priority: %u",
173 (unsigned int) priority);
174 } else {
175 snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: %s, Priority: %u",
176 state_str, (unsigned int) priority);
177 }
178
179 LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable,
180 (unsigned int)task, details->thread_name_str);
181 return 0;
182 }
183
184 static int embKernel_update_threads(struct rtos *rtos)
185 {
186 /* int i = 0; */
187 int retval;
188 const struct embKernel_params *param;
189
190 if (rtos == NULL)
191 return -1;
192
193 if (rtos->rtos_specific_params == NULL)
194 return -3;
195
196 if (rtos->symbols == NULL) {
197 LOG_ERROR("No symbols for embKernel");
198 return -4;
199 }
200
201 if (rtos->symbols[SYMBOL_ID_sCurrentTask].address == 0) {
202 LOG_ERROR("Don't have the thread list head");
203 return -2;
204 }
205
206 /* wipe out previous thread details if any */
207 rtos_free_threadlist(rtos);
208
209 param = (const struct embKernel_params *) rtos->rtos_specific_params;
210
211 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sCurrentTask].address, param->pointer_width,
212 (uint8_t *) &rtos->current_thread);
213 if (retval != ERROR_OK) {
214 LOG_ERROR("Error reading current thread in embKernel thread list");
215 return retval;
216 }
217
218 int64_t max_used_priority = 0;
219 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sMaxPriorities].address, param->pointer_width,
220 (uint8_t *) &max_used_priority);
221 if (retval != ERROR_OK)
222 return retval;
223
224 int thread_list_size = 0;
225 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sCurrentTaskCount].address,
226 param->thread_count_width, (uint8_t *) &thread_list_size);
227
228 if (retval != ERROR_OK) {
229 LOG_ERROR("Could not read embKernel thread count from target");
230 return retval;
231 }
232
233 /* create space for new thread details */
234 rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);
235 if (!rtos->thread_details) {
236 LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
237 return ERROR_FAIL;
238 }
239
240 int threadIdx = 0;
241 /* Look for ready tasks */
242 for (int pri = 0; pri < max_used_priority; pri++) {
243 /* Get first item in queue */
244 int64_t iterable = 0;
245 retval = target_read_buffer(rtos->target,
246 rtos->symbols[SYMBOL_ID_sListReady].address + (pri * param->rtos_list_size), param->pointer_width,
247 (uint8_t *) &iterable);
248 if (retval != ERROR_OK)
249 return retval;
250 for (; iterable && threadIdx < thread_list_size; threadIdx++) {
251 /* Get info from this iterable item */
252 retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Ready");
253 if (retval != ERROR_OK)
254 return retval;
255 /* Get next iterable item */
256 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
257 (uint8_t *) &iterable);
258 if (retval != ERROR_OK)
259 return retval;
260 }
261 }
262 /* Look for sleeping tasks */
263 int64_t iterable = 0;
264 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListSleep].address, param->pointer_width,
265 (uint8_t *) &iterable);
266 if (retval != ERROR_OK)
267 return retval;
268 for (; iterable && threadIdx < thread_list_size; threadIdx++) {
269 /*Get info from this iterable item */
270 retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Sleeping");
271 if (retval != ERROR_OK)
272 return retval;
273 /*Get next iterable item */
274 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
275 (uint8_t *) &iterable);
276 if (retval != ERROR_OK)
277 return retval;
278 }
279
280 /* Look for suspended tasks */
281 iterable = 0;
282 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListSuspended].address, param->pointer_width,
283 (uint8_t *) &iterable);
284 if (retval != ERROR_OK)
285 return retval;
286 for (; iterable && threadIdx < thread_list_size; threadIdx++) {
287 /* Get info from this iterable item */
288 retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Suspended");
289 if (retval != ERROR_OK)
290 return retval;
291 /*Get next iterable item */
292 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
293 (uint8_t *) &iterable);
294 if (retval != ERROR_OK)
295 return retval;
296 }
297
298 rtos->thread_count = 0;
299 rtos->thread_count = threadIdx;
300 LOG_OUTPUT("Found %u tasks\n", (unsigned int)threadIdx);
301 return 0;
302 }
303
304 static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
305 struct rtos_reg **reg_list, int *num_regs)
306 {
307 int retval;
308 const struct embKernel_params *param;
309 int64_t stack_ptr = 0;
310
311 if (rtos == NULL)
312 return -1;
313
314 if (thread_id == 0)
315 return -2;
316
317 if (rtos->rtos_specific_params == NULL)
318 return -1;
319
320 param = (const struct embKernel_params *) rtos->rtos_specific_params;
321
322 /* Read the stack pointer */
323 retval = target_read_buffer(rtos->target, thread_id + param->thread_stack_offset, param->pointer_width,
324 (uint8_t *) &stack_ptr);
325 if (retval != ERROR_OK) {
326 LOG_ERROR("Error reading stack frame from embKernel thread");
327 return retval;
328 }
329
330 return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, reg_list, num_regs);
331 }
332
333 static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
334 {
335 unsigned int i;
336 *symbol_list = calloc(ARRAY_SIZE(embKernel_symbol_list), sizeof(symbol_table_elem_t));
337
338 for (i = 0; i < ARRAY_SIZE(embKernel_symbol_list); i++)
339 (*symbol_list)[i].symbol_name = embKernel_symbol_list[i];
340
341 return 0;
342 }
343

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)