target/riscv: Update debug_defines.h.
[openocd.git] / src / rtos / embKernel.c
blob23e7bc64b83336e4d3ada1f3cf4c305919e9988a
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Copyright (C) 2011 by Broadcom Corporation *
5 * Evan Hunter - ehunter@broadcom.com *
6 ***************************************************************************/
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
12 #include <helper/time_support.h>
13 #include <jtag/jtag.h>
14 #include "target/target.h"
15 #include "target/target_type.h"
16 #include "rtos.h"
17 #include "helper/log.h"
18 #include "helper/types.h"
19 #include "rtos_embkernel_stackings.h"
21 #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
23 static bool embkernel_detect_rtos(struct target *target);
24 static int embkernel_create(struct target *target);
25 static int embkernel_update_threads(struct rtos *rtos);
26 static int embkernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
27 struct rtos_reg **reg_list, int *num_regs);
28 static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
30 struct rtos_type embkernel_rtos = {
31 .name = "embKernel",
32 .detect_rtos = embkernel_detect_rtos,
33 .create = embkernel_create,
34 .update_threads = embkernel_update_threads,
35 .get_thread_reg_list =
36 embkernel_get_thread_reg_list,
37 .get_symbol_list_to_lookup = embkernel_get_symbol_list_to_lookup,
40 enum {
41 SYMBOL_ID_S_CURRENT_TASK = 0,
42 SYMBOL_ID_S_LIST_READY = 1,
43 SYMBOL_ID_S_LIST_SLEEP = 2,
44 SYMBOL_ID_S_LIST_SUSPENDED = 3,
45 SYMBOL_ID_S_MAX_PRIORITIES = 4,
46 SYMBOL_ID_S_CURRENT_TASK_COUNT = 5,
49 static const char * const embkernel_symbol_list[] = {
50 "Rtos::sCurrentTask",
51 "Rtos::sListReady",
52 "Rtos::sListSleep",
53 "Rtos::sListSuspended",
54 "Rtos::sMaxPriorities",
55 "Rtos::sCurrentTaskCount",
56 NULL };
58 struct embkernel_params {
59 const char *target_name;
60 const unsigned char pointer_width;
61 const unsigned char thread_count_width;
62 const unsigned char rtos_list_size;
63 const unsigned char thread_stack_offset;
64 const unsigned char thread_name_offset;
65 const unsigned char thread_priority_offset;
66 const unsigned char thread_priority_width;
67 const unsigned char iterable_next_offset;
68 const unsigned char iterable_task_owner_offset;
69 const struct rtos_register_stacking *stacking_info;
72 static const struct embkernel_params embkernel_params_list[] = {
74 "cortex_m", /* target_name */
75 4, /* pointer_width */
76 4, /* thread_count_width */
77 8, /*rtos_list_size */
78 0, /*thread_stack_offset */
79 4, /*thread_name_offset */
80 8, /*thread_priority_offset */
81 4, /*thread_priority_width */
82 4, /*iterable_next_offset */
83 12, /*iterable_task_owner_offset */
84 &rtos_embkernel_cortex_m_stacking, /* stacking_info*/
86 { "hla_target", /* 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 */
100 static bool embkernel_detect_rtos(struct target *target)
102 if (target->rtos->symbols) {
103 if (target->rtos->symbols[SYMBOL_ID_S_CURRENT_TASK].address != 0)
104 return true;
106 return false;
109 static int embkernel_create(struct target *target)
111 size_t i = 0;
112 while ((i < ARRAY_SIZE(embkernel_params_list)) &&
113 (strcmp(embkernel_params_list[i].target_name, target->type->name) != 0))
114 i++;
116 if (i >= ARRAY_SIZE(embkernel_params_list)) {
117 LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
118 "list", target->type->name);
119 return -1;
122 target->rtos->rtos_specific_params = (void *) &embkernel_params_list[i];
123 return 0;
126 static int embkernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embkernel_params *param,
127 struct thread_detail *details, const char *state_str)
129 int64_t task = 0;
130 int retval = target_read_buffer(rtos->target, iterable + param->iterable_task_owner_offset, param->pointer_width,
131 (uint8_t *) &task);
132 if (retval != ERROR_OK)
133 return retval;
134 details->threadid = (threadid_t) task;
135 details->exists = true;
137 int64_t name_ptr = 0;
138 retval = target_read_buffer(rtos->target, task + param->thread_name_offset, param->pointer_width,
139 (uint8_t *) &name_ptr);
140 if (retval != ERROR_OK)
141 return retval;
143 details->thread_name_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
144 if (name_ptr) {
145 retval = target_read_buffer(rtos->target, name_ptr, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE,
146 (uint8_t *) details->thread_name_str);
147 if (retval != ERROR_OK)
148 return retval;
149 details->thread_name_str[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE - 1] = 0;
150 } else {
151 snprintf(details->thread_name_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "NoName:[0x%08X]", (unsigned int) task);
154 int64_t priority = 0;
155 retval = target_read_buffer(rtos->target, task + param->thread_priority_offset, param->thread_priority_width,
156 (uint8_t *) &priority);
157 if (retval != ERROR_OK)
158 return retval;
159 details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
160 if (task == rtos->current_thread) {
161 snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: Running, Priority: %u",
162 (unsigned int) priority);
163 } else {
164 snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: %s, Priority: %u",
165 state_str, (unsigned int) priority);
168 LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable,
169 (unsigned int)task, details->thread_name_str);
170 return 0;
173 static int embkernel_update_threads(struct rtos *rtos)
175 /* int i = 0; */
176 int retval;
177 const struct embkernel_params *param;
179 if (!rtos)
180 return -1;
182 if (!rtos->rtos_specific_params)
183 return -3;
185 if (!rtos->symbols) {
186 LOG_ERROR("No symbols for embKernel");
187 return -4;
190 if (rtos->symbols[SYMBOL_ID_S_CURRENT_TASK].address == 0) {
191 LOG_ERROR("Don't have the thread list head");
192 return -2;
195 /* wipe out previous thread details if any */
196 rtos_free_threadlist(rtos);
198 param = (const struct embkernel_params *) rtos->rtos_specific_params;
200 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_CURRENT_TASK].address, param->pointer_width,
201 (uint8_t *) &rtos->current_thread);
202 if (retval != ERROR_OK) {
203 LOG_ERROR("Error reading current thread in embKernel thread list");
204 return retval;
207 int64_t max_used_priority = 0;
208 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_MAX_PRIORITIES].address, param->pointer_width,
209 (uint8_t *) &max_used_priority);
210 if (retval != ERROR_OK)
211 return retval;
213 int thread_list_size = 0;
214 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_CURRENT_TASK_COUNT].address,
215 param->thread_count_width, (uint8_t *) &thread_list_size);
217 if (retval != ERROR_OK) {
218 LOG_ERROR("Could not read embKernel thread count from target");
219 return retval;
222 /* create space for new thread details */
223 rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);
224 if (!rtos->thread_details) {
225 LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
226 return ERROR_FAIL;
229 int thread_idx = 0;
230 /* Look for ready tasks */
231 for (int pri = 0; pri < max_used_priority; pri++) {
232 /* Get first item in queue */
233 int64_t iterable = 0;
234 retval = target_read_buffer(rtos->target,
235 rtos->symbols[SYMBOL_ID_S_LIST_READY].address + (pri * param->rtos_list_size), param->pointer_width,
236 (uint8_t *) &iterable);
237 if (retval != ERROR_OK)
238 return retval;
239 for (; iterable && thread_idx < thread_list_size; thread_idx++) {
240 /* Get info from this iterable item */
241 retval = embkernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[thread_idx], "Ready");
242 if (retval != ERROR_OK)
243 return retval;
244 /* Get next iterable item */
245 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
246 (uint8_t *) &iterable);
247 if (retval != ERROR_OK)
248 return retval;
251 /* Look for sleeping tasks */
252 int64_t iterable = 0;
253 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_LIST_SLEEP].address, param->pointer_width,
254 (uint8_t *) &iterable);
255 if (retval != ERROR_OK)
256 return retval;
257 for (; iterable && thread_idx < thread_list_size; thread_idx++) {
258 /*Get info from this iterable item */
259 retval = embkernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[thread_idx], "Sleeping");
260 if (retval != ERROR_OK)
261 return retval;
262 /*Get next iterable item */
263 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
264 (uint8_t *) &iterable);
265 if (retval != ERROR_OK)
266 return retval;
269 /* Look for suspended tasks */
270 iterable = 0;
271 retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_LIST_SUSPENDED].address, param->pointer_width,
272 (uint8_t *) &iterable);
273 if (retval != ERROR_OK)
274 return retval;
275 for (; iterable && thread_idx < thread_list_size; thread_idx++) {
276 /* Get info from this iterable item */
277 retval = embkernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[thread_idx], "Suspended");
278 if (retval != ERROR_OK)
279 return retval;
280 /*Get next iterable item */
281 retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
282 (uint8_t *) &iterable);
283 if (retval != ERROR_OK)
284 return retval;
287 rtos->thread_count = 0;
288 rtos->thread_count = thread_idx;
289 LOG_OUTPUT("Found %u tasks\n", (unsigned int)thread_idx);
290 return 0;
293 static int embkernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
294 struct rtos_reg **reg_list, int *num_regs)
296 int retval;
297 const struct embkernel_params *param;
298 int64_t stack_ptr = 0;
300 if (!rtos)
301 return -1;
303 if (thread_id == 0)
304 return -2;
306 if (!rtos->rtos_specific_params)
307 return -1;
309 param = (const struct embkernel_params *) rtos->rtos_specific_params;
311 /* Read the stack pointer */
312 retval = target_read_buffer(rtos->target, thread_id + param->thread_stack_offset, param->pointer_width,
313 (uint8_t *) &stack_ptr);
314 if (retval != ERROR_OK) {
315 LOG_ERROR("Error reading stack frame from embKernel thread");
316 return retval;
319 return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, reg_list, num_regs);
322 static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
324 unsigned int i;
325 *symbol_list = calloc(ARRAY_SIZE(embkernel_symbol_list), sizeof(struct symbol_table_elem));
327 for (i = 0; i < ARRAY_SIZE(embkernel_symbol_list); i++)
328 (*symbol_list)[i].symbol_name = embkernel_symbol_list[i];
330 return 0;