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
,