1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 ***************************************************************************/
10 #include <helper/time_support.h>
11 #include <jtag/jtag.h>
12 #include "target/target.h"
13 #include "target/target_type.h"
15 #include "helper/log.h"
16 #include "helper/types.h"
17 #include "rtos_ecos_stackings.h"
19 static bool ecos_detect_rtos(struct target *target);
20 static int ecos_create(struct target *target);
21 static int ecos_update_threads(struct rtos *rtos);
22 static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs);
23 static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
25 struct ecos_thread_state {
30 static const struct ecos_thread_state ecos_thread_states[] = {
39 #define ECOS_NUM_STATES ARRAY_SIZE(ecos_thread_states)
42 const char *target_name;
43 unsigned char pointer_width;
44 unsigned char thread_stack_offset;
45 unsigned char thread_name_offset;
46 unsigned char thread_state_offset;
47 unsigned char thread_next_offset;
48 unsigned char thread_uniqueid_offset;
49 const struct rtos_register_stacking *stacking_info;
52 static const struct ecos_params ecos_params_list[] = {
54 "cortex_m", /* target_name */
55 4, /* pointer_width; */
56 0x0c, /* thread_stack_offset; */
57 0x9c, /* thread_name_offset; */
58 0x3c, /* thread_state_offset; */
59 0xa0, /* thread_next_offset */
60 0x4c, /* thread_uniqueid_offset */
61 &rtos_ecos_cortex_m3_stacking /* stacking_info */
65 enum ecos_symbol_values {
66 ECOS_VAL_THREAD_LIST = 0,
67 ECOS_VAL_CURRENT_THREAD_PTR = 1
70 static const char * const ecos_symbol_list[] = {
71 "Cyg_Thread::thread_list",
72 "Cyg_Scheduler_Base::current_thread",
76 const struct rtos_type ecos_rtos = {
79 .detect_rtos = ecos_detect_rtos,
80 .create = ecos_create,
81 .update_threads = ecos_update_threads,
82 .get_thread_reg_list = ecos_get_thread_reg_list,
83 .get_symbol_list_to_lookup = ecos_get_symbol_list_to_lookup,
87 static int ecos_update_threads(struct rtos *rtos)
91 int thread_list_size = 0;
92 const struct ecos_params *param;
97 if (!rtos->rtos_specific_params)
100 param = (const struct ecos_params *) rtos->rtos_specific_params;
102 if (!rtos->symbols) {
103 LOG_ERROR("No symbols for eCos");
107 if (rtos->symbols[ECOS_VAL_THREAD_LIST].address == 0) {
108 LOG_ERROR("Don't have the thread list head");
112 /* wipe out previous thread details if any */
113 rtos_free_threadlist(rtos);
115 /* determine the number of current threads */
116 uint32_t thread_list_head = rtos->symbols[ECOS_VAL_THREAD_LIST].address;
117 uint32_t thread_index;
118 target_read_buffer(rtos->target,
120 param->pointer_width,
121 (uint8_t *) &thread_index);
122 uint32_t first_thread = thread_index;
125 retval = target_read_buffer(rtos->target,
126 thread_index + param->thread_next_offset,
127 param->pointer_width,
128 (uint8_t *) &thread_index);
129 if (retval != ERROR_OK)
131 } while (thread_index != first_thread);
133 /* read the current thread id */
134 uint32_t current_thread_addr;
135 retval = target_read_buffer(rtos->target,
136 rtos->symbols[ECOS_VAL_CURRENT_THREAD_PTR].address,
138 (uint8_t *)¤t_thread_addr);
139 if (retval != ERROR_OK)
141 rtos->current_thread = 0;
142 retval = target_read_buffer(rtos->target,
143 current_thread_addr + param->thread_uniqueid_offset,
145 (uint8_t *)&rtos->current_thread);
146 if (retval != ERROR_OK) {
147 LOG_ERROR("Could not read eCos current thread from target");
151 if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
152 /* Either : No RTOS threads - there is always at least the current execution though */
153 /* OR : No current thread - all threads suspended - show the current execution
155 char tmp_str[] = "Current Execution";
158 rtos->thread_details = malloc(
159 sizeof(struct thread_detail) * thread_list_size);
160 rtos->thread_details->threadid = 1;
161 rtos->thread_details->exists = true;
162 rtos->thread_details->extra_info_str = NULL;
163 rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
164 strcpy(rtos->thread_details->thread_name_str, tmp_str);
166 if (thread_list_size == 0) {
167 rtos->thread_count = 1;
171 /* create space for new thread details */
172 rtos->thread_details = malloc(
173 sizeof(struct thread_detail) * thread_list_size);
176 /* loop over all threads */
177 thread_index = first_thread;
180 #define ECOS_THREAD_NAME_STR_SIZE (200)
181 char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
183 uint32_t name_ptr = 0;
184 uint32_t prev_thread_ptr;
186 /* Save the thread pointer */
188 retval = target_read_buffer(rtos->target,
189 thread_index + param->thread_uniqueid_offset,
191 (uint8_t *)&thread_id);
192 if (retval != ERROR_OK) {
193 LOG_ERROR("Could not read eCos thread id from target");
196 rtos->thread_details[tasks_found].threadid = thread_id;
198 /* read the name pointer */
199 retval = target_read_buffer(rtos->target,
200 thread_index + param->thread_name_offset,
201 param->pointer_width,
202 (uint8_t *)&name_ptr);
203 if (retval != ERROR_OK) {
204 LOG_ERROR("Could not read eCos thread name pointer from target");
208 /* Read the thread name */
210 target_read_buffer(rtos->target,
212 ECOS_THREAD_NAME_STR_SIZE,
213 (uint8_t *)&tmp_str);
214 if (retval != ERROR_OK) {
215 LOG_ERROR("Error reading thread name from eCos target");
218 tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
220 if (tmp_str[0] == '\x00')
221 strcpy(tmp_str, "No Name");
223 rtos->thread_details[tasks_found].thread_name_str =
224 malloc(strlen(tmp_str)+1);
225 strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
227 /* Read the thread status */
228 int64_t thread_status = 0;
229 retval = target_read_buffer(rtos->target,
230 thread_index + param->thread_state_offset,
232 (uint8_t *)&thread_status);
233 if (retval != ERROR_OK) {
234 LOG_ERROR("Error reading thread state from eCos target");
238 for (i = 0; (i < ECOS_NUM_STATES) && (ecos_thread_states[i].value != thread_status); i++) {
244 const char *state_desc;
245 if (i < ECOS_NUM_STATES)
246 state_desc = ecos_thread_states[i].desc;
248 state_desc = "Unknown state";
250 rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
252 sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc);
254 rtos->thread_details[tasks_found].exists = true;
257 prev_thread_ptr = thread_index;
259 /* Get the location of the next thread structure. */
260 thread_index = rtos->symbols[ECOS_VAL_THREAD_LIST].address;
261 retval = target_read_buffer(rtos->target,
262 prev_thread_ptr + param->thread_next_offset,
263 param->pointer_width,
264 (uint8_t *) &thread_index);
265 if (retval != ERROR_OK) {
266 LOG_ERROR("Error reading next thread pointer in eCos thread list");
269 } while (thread_index != first_thread);
271 rtos->thread_count = tasks_found;
275 static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
276 struct rtos_reg **reg_list, int *num_regs)
279 const struct ecos_params *param;
287 if (!rtos->rtos_specific_params)
290 param = (const struct ecos_params *) rtos->rtos_specific_params;
292 /* Find the thread with that thread id */
294 uint32_t thread_list_head = rtos->symbols[ECOS_VAL_THREAD_LIST].address;
295 uint32_t thread_index;
296 target_read_buffer(rtos->target, thread_list_head, param->pointer_width,
297 (uint8_t *)&thread_index);
300 retval = target_read_buffer(rtos->target,
301 thread_index + param->thread_uniqueid_offset,
304 if (retval != ERROR_OK) {
305 LOG_ERROR("Error reading unique id from eCos thread");
309 if (id == thread_id) {
313 target_read_buffer(rtos->target,
314 thread_index + param->thread_next_offset,
315 param->pointer_width,
316 (uint8_t *) &thread_index);
320 /* Read the stack pointer */
321 int64_t stack_ptr = 0;
322 retval = target_read_buffer(rtos->target,
323 thread_index + param->thread_stack_offset,
324 param->pointer_width,
325 (uint8_t *)&stack_ptr);
326 if (retval != ERROR_OK) {
327 LOG_ERROR("Error reading stack frame from eCos thread");
331 return rtos_generic_stack_read(rtos->target,
332 param->stacking_info,
341 static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
344 *symbol_list = calloc(
345 ARRAY_SIZE(ecos_symbol_list), sizeof(struct symbol_table_elem));
347 for (i = 0; i < ARRAY_SIZE(ecos_symbol_list); i++)
348 (*symbol_list)[i].symbol_name = ecos_symbol_list[i];
353 static bool ecos_detect_rtos(struct target *target)
355 if ((target->rtos->symbols) &&
356 (target->rtos->symbols[ECOS_VAL_THREAD_LIST].address != 0)) {
357 /* looks like eCos */
363 static int ecos_create(struct target *target)
365 for (unsigned int i = 0; i < ARRAY_SIZE(ecos_params_list); i++)
366 if (strcmp(ecos_params_list[i].target_name, target->type->name) == 0) {
367 target->rtos->rtos_specific_params = (void *)&ecos_params_list[i];
368 target->rtos->current_thread = 0;
369 target->rtos->thread_details = NULL;
373 LOG_ERROR("Could not find target in eCos compatibility list");