Restore -dev suffix
[openocd.git] / src / rtos / embKernel.c
blob9f5fa50f073e179529616a501f98b26ed33aaa3c
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 ***************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
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_embkernel_stackings.h"
34 #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
36 static int embKernel_detect_rtos(struct target *target);
37 static int embKernel_create(struct target *target);
38 static int embKernel_update_threads(struct rtos *rtos);
39 static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
40 static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
42 struct rtos_type embKernel_rtos = {
43 .name = "embKernel",
44 .detect_rtos = embKernel_detect_rtos,
45 .create = embKernel_create,
46 .update_threads = embKernel_update_threads,
47 .get_thread_reg_list =
48 embKernel_get_thread_reg_list,
49 .get_symbol_list_to_lookup = embKernel_get_symbol_list_to_lookup,
52 enum {
53 SYMBOL_ID_sCurrentTask = 0,
54 SYMBOL_ID_sListReady = 1,
55 SYMBOL_ID_sListSleep = 2,
56 SYMBOL_ID_sListSuspended = 3,
57 SYMBOL_ID_sMaxPriorities = 4,
58 SYMBOL_ID_sCurrentTaskCount = 5,
61 static char *embKernel_symbol_list[] = {
62 "Rtos::sCurrentTask",
63 "Rtos::sListReady",
64 "Rtos::sListSleep",
65 "Rtos::sListSuspended",
66 "Rtos::sMaxPriorities",
67 "Rtos::sCurrentTaskCount",
68 NULL };
70 struct embKernel_params {
71 const char *target_name;
72 const unsigned char pointer_width;
73 const unsigned char thread_count_width;
74 const unsigned char rtos_list_size;
75 const unsigned char thread_stack_offset;
76 const unsigned char thread_name_offset;
77 const unsigned char thread_priority_offset;
78 const unsigned char thread_priority_width;
79 const unsigned char iterable_next_offset;
80 const unsigned char iterable_task_owner_offset;
81 const struct rtos_register_stacking *stacking_info;
84 struct embKernel_params embKernel_params_list[] = {
86 "cortex_m", /* target_name */
87 4, /* pointer_width */
88 4, /* thread_count_width */
89 8, /*rtos_list_size */
90 0, /*thread_stack_offset */
91 4, /*thread_name_offset */
92 8, /*thread_priority_offset */
93 4, /*thread_priority_width */
94 4, /*iterable_next_offset */
95 12, /*iterable_task_owner_offset */
96 &rtos_embkernel_Cortex_M_stacking, /* stacking_info*/
98 { "hla_target", /* target_name */
99 4, /* pointer_width */
100 4, /* thread_count_width */
101 8, /*rtos_list_size */
102 0, /*thread_stack_offset */
103 4, /*thread_name_offset */
104 8, /*thread_priority_offset */
105 4, /*thread_priority_width */
106 4, /*iterable_next_offset */
107 12, /*iterable_task_owner_offset */
108 &rtos_embkernel_Cortex_M_stacking, /* stacking_info */
112 static int embKernel_detect_rtos(struct target *target)
114 if (target->rtos->symbols != NULL) {
115 if (target->rtos->symbols[SYMBOL_ID_sCurrentTask].address != 0)
116 return 1;
118 return 0;
121 static int embKernel_create(struct target *target)
123 size_t i = 0;
124 while ((i < ARRAY_SIZE(embKernel_params_list)) &&
125 (0 != strcmp(embKernel_params_list[i].target_name, target->type->name)))
126 i++;
128 if (i >= ARRAY_SIZE(embKernel_params_list)) {
129 LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
130 "list", target->type->name);
131 return -1;
134 target->rtos->rtos_specific_params = &embKernel_params_list[i];
135 return 0;
138 static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embKernel_params *param,
139 struct thread_detail *details, const char* state_str)
141 int64_t task = 0;
142 int retval = target_read_buffer(rtos->target, iterable + param->iterable_task_owner_offset, param->pointer_width,
143 (uint8_t *) &task);
144 if (retval != ERROR_OK)
145 return retval;
146 details->threadid = (threadid_t) task;
147 details->exists = true;
148 details->display_str = NULL;
150 int64_t name_ptr = 0;
151 retval = target_read_buffer(rtos->target, task + param->thread_name_offset, param->pointer_width,
152 (uint8_t *) &name_ptr);
153 if (retval != ERROR_OK)
154 return retval;
156 details->thread_name_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
157 if (name_ptr) {
158 retval = target_read_buffer(rtos->target, name_ptr, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE,
159 (uint8_t *) details->thread_name_str);
160 if (retval != ERROR_OK)
161 return retval;
162 details->thread_name_str[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE - 1] = 0;
163 } else {
164 snprintf(details->thread_name_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "NoName:[0x%08X]", (unsigned int) task);
167 int64_t priority = 0;
168 retval = target_read_buffer(rtos->target, task + param->thread_priority_offset, param->thread_priority_width,
169 (uint8_t *) &priority);
170 if (retval != ERROR_OK)
171 return retval;
172 details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
173 if (task == rtos->current_thread) {
174 snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, Running",
175 (unsigned int) priority);
176 } else {
177 snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, %s", (unsigned int) priority,
178 state_str);
181 LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable,
182 (unsigned int)task, details->thread_name_str);
183 return 0;
186 static int embKernel_update_threads(struct rtos *rtos)
188 /* int i = 0; */
189 int retval;
190 const struct embKernel_params *param;
192 if (rtos == NULL)
193 return -1;
195 if (rtos->rtos_specific_params == NULL)
196 return -3;
198 if (rtos->symbols == NULL) {
199 LOG_ERROR("No symbols for embKernel");
200 return -4;
203 if (rtos->symbols[SYMBOL_ID_sCurrentTask].address == 0) {
204 LOG_ERROR("Don't have the thread list head");
205 return -2;
208 /* wipe out previous thread details if any */
209 rtos_free_threadlist(rtos);
211 param = (const struct embKernel_params *) rtos->rtos_specific_params;
213 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sCurrentTask].address, param->pointer_width,
214 (uint8_t *) &rtos->current_thread);
215 if (retval != ERROR_OK) {
216 LOG_ERROR("Error reading current thread in embKernel thread list");
217 return retval;
220 int64_t max_used_priority = 0;
221 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sMaxPriorities].address, param->pointer_width,
222 (uint8_t *) &max_used_priority);
223 if (retval != ERROR_OK)
224 return retval;
226 int thread_list_size = 0;
227 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sCurrentTaskCount].address,
228 param->thread_count_width, (uint8_t *) &thread_list_size);
230 if (retval != ERROR_OK) {
231 LOG_ERROR("Could not read embKernel thread count from target");
232 return retval;
235 /* create space for new thread details */
236 rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);
237 if (!rtos->thread_details) {
238 LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
239 return ERROR_FAIL;
242 int threadIdx = 0;
243 /* Look for ready tasks */
244 for (int pri = 0; pri < max_used_priority; pri++) {
245 /* Get first item in queue */
246 int64_t iterable = 0;
247 retval = target_read_buffer(rtos->target,
248 rtos->symbols[SYMBOL_ID_sListReady].address + (pri * param->rtos_list_size), param->pointer_width,
249 (uint8_t *) &iterable);
250 if (retval != ERROR_OK)
251 return retval;
252 for (; iterable && threadIdx < thread_list_size; threadIdx++) {
253 /* Get info from this iterable item */
254 retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Ready");
255 if (retval != ERROR_OK)
256 return retval;
257 /* Get next iterable item */
258 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
259 (uint8_t *) &iterable);
260 if (retval != ERROR_OK)
261 return retval;
264 /* Look for sleeping tasks */
265 int64_t iterable = 0;
266 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListSleep].address, param->pointer_width,
267 (uint8_t *) &iterable);
268 if (retval != ERROR_OK)
269 return retval;
270 for (; iterable && threadIdx < thread_list_size; threadIdx++) {
271 /*Get info from this iterable item */
272 retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Sleeping");
273 if (retval != ERROR_OK)
274 return retval;
275 /*Get next iterable item */
276 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
277 (uint8_t *) &iterable);
278 if (retval != ERROR_OK)
279 return retval;
282 /* Look for suspended tasks */
283 iterable = 0;
284 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_sListSuspended].address, param->pointer_width,
285 (uint8_t *) &iterable);
286 if (retval != ERROR_OK)
287 return retval;
288 for (; iterable && threadIdx < thread_list_size; threadIdx++) {
289 /* Get info from this iterable item */
290 retval = embKernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[threadIdx], "Suspended");
291 if (retval != ERROR_OK)
292 return retval;
293 /*Get next iterable item */
294 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
295 (uint8_t *) &iterable);
296 if (retval != ERROR_OK)
297 return retval;
300 rtos->thread_count = 0;
301 rtos->thread_count = threadIdx;
302 LOG_OUTPUT("Found %u tasks\n", (unsigned int)threadIdx);
303 return 0;
306 static int embKernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
308 int retval;
309 const struct embKernel_params *param;
310 int64_t stack_ptr = 0;
312 *hex_reg_list = NULL;
313 if (rtos == NULL)
314 return -1;
316 if (thread_id == 0)
317 return -2;
319 if (rtos->rtos_specific_params == NULL)
320 return -1;
322 param = (const struct embKernel_params *) rtos->rtos_specific_params;
324 /* Read the stack pointer */
325 retval = target_read_buffer(rtos->target, thread_id + param->thread_stack_offset, param->pointer_width,
326 (uint8_t *) &stack_ptr);
327 if (retval != ERROR_OK) {
328 LOG_ERROR("Error reading stack frame from embKernel thread");
329 return retval;
332 return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list);
335 static int embKernel_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
337 unsigned int i;
338 *symbol_list = malloc(sizeof(symbol_table_elem_t) * ARRAY_SIZE(embKernel_symbol_list));
340 for (i = 0; i < ARRAY_SIZE(embKernel_symbol_list); i++)
341 (*symbol_list)[i].symbol_name = embKernel_symbol_list[i];
343 return 0;