2 * SPDX-License-Identifier: GPL-2.0
4 * Copyright (c) 2018 National Instruments Corp
5 * Author: Moritz Fischer <moritz.fischer@ettus.com>
7 * Chromium-EC RTOS Task Awareness
10 #include <rtos/rtos.h>
11 #include <target/target.h>
12 #include <target/target_type.h>
14 #include "rtos_standard_stackings.h"
16 #define CROS_EC_MAX_TASKS 32
17 #define CROS_EC_MAX_NAME 200
18 #define CROS_EC_IDLE_STRING "<< idle >>"
19 #define BIT(x) (1 << (x))
21 struct chromium_ec_params {
22 const char *target_name;
24 off_t task_offset_next;
26 off_t task_offset_events;
27 off_t task_offset_runtime;
28 const struct rtos_register_stacking *stacking;
31 static const struct chromium_ec_params chromium_ec_params_list[] = {
33 .target_name = "hla_target",
35 .task_offset_next = 24,
37 .task_offset_events = 4,
38 .task_offset_runtime = 8,
39 .stacking = &rtos_standard_Cortex_M3_stacking,
43 .target_name = "cortex_m",
45 .task_offset_next = 24,
47 .task_offset_events = 4,
48 .task_offset_runtime = 8,
49 .stacking = &rtos_standard_Cortex_M3_stacking,
53 static const char * const chromium_ec_symbol_list[] = {
64 enum chromium_ec_symbol_values {
65 CHROMIUM_EC_VAL_start_called = 0,
66 CHROMIUM_EC_VAL_current_task,
67 CHROMIUM_EC_VAL_tasks,
68 CHROMIUM_EC_VAL_tasks_enabled,
69 CHROMIUM_EC_VAL_tasks_ready,
70 CHROMIUM_EC_VAL_task_names,
71 CHROMIUM_EC_VAL_build_info,
73 CHROMIUM_EC_VAL_COUNT,
76 #define CROS_EC_MAX_BUILDINFO 512
78 static bool chromium_ec_detect_rtos(struct target *target)
80 char build_info_buf[CROS_EC_MAX_BUILDINFO];
81 enum chromium_ec_symbol_values sym;
84 if (!target || !target->rtos || !target->rtos->symbols)
87 for (sym = CHROMIUM_EC_VAL_start_called;
88 sym < CHROMIUM_EC_VAL_COUNT; sym++) {
89 if (target->rtos->symbols[sym].address) {
90 LOG_DEBUG("Chromium-EC: Symbol \"%s\" found",
91 chromium_ec_symbol_list[sym]);
93 LOG_ERROR("Chromium-EC: Symbol \"%s\" missing",
94 chromium_ec_symbol_list[sym]);
99 ret = target_read_buffer(target,
100 target->rtos->symbols[CHROMIUM_EC_VAL_build_info].address,
101 sizeof(build_info_buf),
102 (uint8_t *)build_info_buf);
107 LOG_INFO("Chromium-EC: Buildinfo: %s", build_info_buf);
109 return target->rtos->symbols &&
110 target->rtos->symbols[CHROMIUM_EC_VAL_start_called].address;
113 static int chromium_ec_create(struct target *target)
115 struct chromium_ec_params *params;
118 for (t = 0; t < ARRAY_SIZE(chromium_ec_params_list); t++)
119 if (!strcmp(chromium_ec_params_list[t].target_name, target->type->name)) {
120 params = malloc(sizeof(*params));
122 LOG_ERROR("Chromium-EC: out of memory");
126 memcpy(params, &chromium_ec_params_list[t], sizeof(*params));
127 target->rtos->rtos_specific_params = (void *)params;
128 target->rtos->current_thread = 0;
129 target->rtos->thread_details = NULL;
130 target->rtos->thread_count = 0;
132 LOG_INFO("Chromium-EC: Using target: %s", target->type->name);
136 LOG_ERROR("Chromium-EC: target not supported: %s", target->type->name);
140 static int chromium_ec_get_current_task_ptr(struct rtos *rtos, uint32_t *current_task)
142 if (!rtos || !rtos->symbols)
145 return target_read_u32(rtos->target,
146 rtos->symbols[CHROMIUM_EC_VAL_current_task].address,
150 static int chromium_ec_get_num_tasks(struct rtos *rtos, int *num_tasks)
152 uint32_t tasks_enabled;
155 ret = target_read_u32(rtos->target,
156 rtos->symbols[CHROMIUM_EC_VAL_tasks_enabled].address,
158 if (ret != ERROR_OK) {
159 LOG_ERROR("Failed to determine #of tasks");
164 for (t = 0; t < CROS_EC_MAX_TASKS; t++)
165 if (tasks_enabled & BIT(t))
173 static int chromium_ec_update_threads(struct rtos *rtos)
175 uint32_t tasks_enabled, tasks_ready, start_called;
176 uint32_t current_task, thread_ptr, name_ptr;
177 char thread_str_buf[CROS_EC_MAX_NAME];
178 int ret, t, num_tasks, tasks_found;
179 struct chromium_ec_params *params;
180 uint8_t runtime_buf[8];
184 params = rtos->rtos_specific_params;
192 ret = chromium_ec_get_num_tasks(rtos, &num_tasks);
193 if (ret != ERROR_OK) {
194 LOG_ERROR("Failed to get number of tasks");
199 ret = chromium_ec_get_current_task_ptr(rtos, ¤t_task);
200 if (ret != ERROR_OK) {
201 LOG_ERROR("Failed to get current task");
204 LOG_DEBUG("Current task: %lx tasks_found: %d",
205 (unsigned long)current_task,
208 /* set current task to what we read */
209 rtos->current_thread = current_task;
211 /* Nuke the old tasks */
212 rtos_free_threadlist(rtos);
214 /* One check if task switching has started ... */
216 ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_start_called].address,
218 if (ret != ERROR_OK) {
219 LOG_ERROR("Failed to load start_called");
223 if (!rtos->current_thread || !num_tasks || !start_called) {
226 rtos->thread_details = malloc(
227 sizeof(struct thread_detail) * num_tasks);
228 rtos->thread_details->threadid = 1;
229 rtos->thread_details->exists = true;
230 rtos->thread_details->extra_info_str = NULL;
231 rtos->thread_details->thread_name_str = strdup("Current Execution");
233 if (!num_tasks || !start_called) {
234 rtos->thread_count = 1;
238 /* create space for new thread details */
239 rtos->thread_details = malloc(
240 sizeof(struct thread_detail) * num_tasks);
244 ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_tasks_enabled].address,
246 if (ret != ERROR_OK) {
247 LOG_ERROR("Failed to load tasks_enabled");
252 ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_tasks_ready].address,
254 if (ret != ERROR_OK) {
255 LOG_ERROR("Failed to load tasks_ready");
259 thread_ptr = rtos->symbols[CHROMIUM_EC_VAL_tasks].address;
262 for (t = 0; t < CROS_EC_MAX_TASKS; t++) {
263 if (!(tasks_enabled & BIT(t)))
266 if (thread_ptr == current_task)
267 rtos->current_thread = thread_ptr;
269 rtos->thread_details[tasks_found].threadid = thread_ptr;
270 ret = target_read_u32(rtos->target,
271 rtos->symbols[CHROMIUM_EC_VAL_task_names].address +
272 params->ptr_size * t, &name_ptr);
273 if (ret != ERROR_OK) {
274 LOG_ERROR("Failed to read name_ptr");
278 /* read name buffer */
279 ret = target_read_buffer(rtos->target, name_ptr, CROS_EC_MAX_NAME,
280 (uint8_t *)thread_str_buf);
281 if (ret != ERROR_OK) {
282 LOG_ERROR("Failed to read task name");
286 /* sanitize string, gdb chokes on "<< idle >>" */
287 if (thread_str_buf[CROS_EC_MAX_NAME - 1] != '\0')
288 thread_str_buf[CROS_EC_MAX_NAME - 1] = '\0';
289 if (!strncmp(thread_str_buf, CROS_EC_IDLE_STRING, CROS_EC_MAX_NAME))
290 rtos->thread_details[tasks_found].thread_name_str = strdup("IDLE");
292 rtos->thread_details[tasks_found].thread_name_str = strdup(thread_str_buf);
295 ret = target_read_u32(rtos->target,
296 thread_ptr + params->task_offset_events,
299 LOG_ERROR("Failed to get task %d's events", t);
301 /* this is a bit kludgy but will do for now */
302 ret = target_read_buffer(rtos->target,
303 thread_ptr + params->task_offset_runtime,
304 sizeof(runtime_buf), runtime_buf);
306 LOG_ERROR("Failed to get task %d's runtime", t);
307 runtime = target_buffer_get_u64(rtos->target, runtime_buf);
309 /* Priority is simply the position in the array */
310 if (thread_ptr == current_task)
311 snprintf(thread_str_buf, sizeof(thread_str_buf),
312 "State: Running, Priority: %u, Events: %" PRIx32 ", Runtime: %" PRIu64 "\n",
315 snprintf(thread_str_buf, sizeof(thread_str_buf),
316 "State: %s, Priority: %u, Events: %" PRIx32 ", Runtime: %" PRIu64 "\n",
317 tasks_ready & BIT(t) ? "Ready" : "Waiting", t,
320 rtos->thread_details[tasks_found].extra_info_str = strdup(thread_str_buf);
321 rtos->thread_details[tasks_found].exists = true;
323 thread_ptr += params->task_offset_next;
328 rtos->thread_count = tasks_found;
333 static int chromium_ec_get_thread_reg_list(struct rtos *rtos,
335 struct rtos_reg **reg_list,
338 struct chromium_ec_params *params = rtos->rtos_specific_params;
339 uint32_t stack_ptr = 0;
342 for (t = 0; t < rtos->thread_count; t++)
343 if (threadid == rtos->thread_details[t].threadid)
346 /* if we didn't find threadid, bail */
347 if (t == rtos->thread_count)
350 ret = target_read_u32(rtos->target,
351 rtos->symbols[CHROMIUM_EC_VAL_tasks].address +
352 params->task_offset_next * t,
354 if (ret != ERROR_OK) {
355 LOG_ERROR("Failed to load TCB");
359 return rtos_generic_stack_read(rtos->target, params->stacking,
360 stack_ptr, reg_list, num_regs);
363 static int chromium_ec_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
367 *symbol_list = calloc(ARRAY_SIZE(chromium_ec_symbol_list),
368 sizeof(struct symbol_table_elem));
369 if (!(*symbol_list)) {
370 LOG_ERROR("Chromium-EC: out of memory");
374 for (s = 0; s < ARRAY_SIZE(chromium_ec_symbol_list); s++)
375 (*symbol_list)[s].symbol_name = chromium_ec_symbol_list[s];
380 const struct rtos_type chromium_ec_rtos = {
381 .name = "Chromium-EC",
382 .detect_rtos = chromium_ec_detect_rtos,
383 .create = chromium_ec_create,
384 .update_threads = chromium_ec_update_threads,
385 .get_thread_reg_list = chromium_ec_get_thread_reg_list,
386 .get_symbol_list_to_lookup = chromium_ec_get_symbol_list_to_lookup,