openocd/src/rtos/chromium-ec.c
Antonio Borneo a489058d7b rtos: rename CamelCase symbols
Only one exported symbol from eCos is included in this patch.
The eCos code is left untouched to prevent conflicts with patches
currently under review.

While there, remove an unused camelcase macro

Change-Id: I8d22dec6e243c00665d99a8b8ba00474b4f088db
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/6305
Tested-by: jenkins
Reviewed-by: Marc Schink <dev@zapb.de>
2021-07-02 17:11:13 +01:00

388 lines
10 KiB
C

/*
* SPDX-License-Identifier: GPL-2.0
*
* Copyright (c) 2018 National Instruments Corp
* Author: Moritz Fischer <moritz.fischer@ettus.com>
*
* Chromium-EC RTOS Task Awareness
*/
#include <rtos/rtos.h>
#include <target/target.h>
#include <target/target_type.h>
#include "rtos_standard_stackings.h"
#define CROS_EC_MAX_TASKS 32
#define CROS_EC_MAX_NAME 200
#define CROS_EC_IDLE_STRING "<< idle >>"
#define BIT(x) (1 << (x))
struct chromium_ec_params {
const char *target_name;
size_t ptr_size;
off_t task_offset_next;
off_t task_offset_sp;
off_t task_offset_events;
off_t task_offset_runtime;
const struct rtos_register_stacking *stacking;
};
static const struct chromium_ec_params chromium_ec_params_list[] = {
{
.target_name = "hla_target",
.ptr_size = 4,
.task_offset_next = 24,
.task_offset_sp = 0,
.task_offset_events = 4,
.task_offset_runtime = 8,
.stacking = &rtos_standard_cortex_m3_stacking,
},
{
.target_name = "cortex_m",
.ptr_size = 4,
.task_offset_next = 24,
.task_offset_sp = 0,
.task_offset_events = 4,
.task_offset_runtime = 8,
.stacking = &rtos_standard_cortex_m3_stacking,
},
};
static const char * const chromium_ec_symbol_list[] = {
"start_called",
"current_task",
"tasks",
"tasks_enabled",
"tasks_ready",
"task_names",
"build_info",
NULL,
};
enum chromium_ec_symbol_values {
CHROMIUM_EC_VAL_START_CALLED = 0,
CHROMIUM_EC_VAL_CURRENT_TASK,
CHROMIUM_EC_VAL_TASKS,
CHROMIUM_EC_VAL_TASKS_ENABLED,
CHROMIUM_EC_VAL_TASKS_READY,
CHROMIUM_EC_VAL_TASK_NAMES,
CHROMIUM_EC_VAL_BUILD_INFO,
CHROMIUM_EC_VAL_COUNT,
};
#define CROS_EC_MAX_BUILDINFO 512
static bool chromium_ec_detect_rtos(struct target *target)
{
char build_info_buf[CROS_EC_MAX_BUILDINFO];
enum chromium_ec_symbol_values sym;
int ret;
if (!target || !target->rtos || !target->rtos->symbols)
return false;
for (sym = CHROMIUM_EC_VAL_START_CALLED;
sym < CHROMIUM_EC_VAL_COUNT; sym++) {
if (target->rtos->symbols[sym].address) {
LOG_DEBUG("Chromium-EC: Symbol \"%s\" found",
chromium_ec_symbol_list[sym]);
} else {
LOG_ERROR("Chromium-EC: Symbol \"%s\" missing",
chromium_ec_symbol_list[sym]);
return false;
}
}
ret = target_read_buffer(target,
target->rtos->symbols[CHROMIUM_EC_VAL_BUILD_INFO].address,
sizeof(build_info_buf),
(uint8_t *)build_info_buf);
if (ret != ERROR_OK)
return false;
LOG_INFO("Chromium-EC: Buildinfo: %s", build_info_buf);
return target->rtos->symbols &&
target->rtos->symbols[CHROMIUM_EC_VAL_START_CALLED].address;
}
static int chromium_ec_create(struct target *target)
{
struct chromium_ec_params *params;
size_t t;
for (t = 0; t < ARRAY_SIZE(chromium_ec_params_list); t++)
if (!strcmp(chromium_ec_params_list[t].target_name, target->type->name)) {
params = malloc(sizeof(*params));
if (!params) {
LOG_ERROR("Chromium-EC: out of memory");
return ERROR_FAIL;
}
memcpy(params, &chromium_ec_params_list[t], sizeof(*params));
target->rtos->rtos_specific_params = (void *)params;
target->rtos->current_thread = 0;
target->rtos->thread_details = NULL;
target->rtos->thread_count = 0;
LOG_INFO("Chromium-EC: Using target: %s", target->type->name);
return ERROR_OK;
}
LOG_ERROR("Chromium-EC: target not supported: %s", target->type->name);
return ERROR_FAIL;
}
static int chromium_ec_get_current_task_ptr(struct rtos *rtos, uint32_t *current_task)
{
if (!rtos || !rtos->symbols)
return ERROR_FAIL;
return target_read_u32(rtos->target,
rtos->symbols[CHROMIUM_EC_VAL_CURRENT_TASK].address,
current_task);
}
static int chromium_ec_get_num_tasks(struct rtos *rtos, int *num_tasks)
{
uint32_t tasks_enabled;
int ret, t, found;
ret = target_read_u32(rtos->target,
rtos->symbols[CHROMIUM_EC_VAL_TASKS_ENABLED].address,
&tasks_enabled);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to determine #of tasks");
return ret;
}
found = 0;
for (t = 0; t < CROS_EC_MAX_TASKS; t++)
if (tasks_enabled & BIT(t))
found++;
*num_tasks = found;
return ERROR_OK;
}
static int chromium_ec_update_threads(struct rtos *rtos)
{
uint32_t tasks_enabled, tasks_ready, start_called;
uint32_t current_task, thread_ptr, name_ptr;
char thread_str_buf[CROS_EC_MAX_NAME];
int ret, t, num_tasks, tasks_found;
struct chromium_ec_params *params;
uint8_t runtime_buf[8];
uint64_t runtime;
uint32_t events;
params = rtos->rtos_specific_params;
if (!params)
return ERROR_FAIL;
if (!rtos->symbols)
return ERROR_FAIL;
num_tasks = 0;
ret = chromium_ec_get_num_tasks(rtos, &num_tasks);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to get number of tasks");
return ret;
}
current_task = 0;
ret = chromium_ec_get_current_task_ptr(rtos, &current_task);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to get current task");
return ret;
}
LOG_DEBUG("Current task: %lx tasks_found: %d",
(unsigned long)current_task,
num_tasks);
/* set current task to what we read */
rtos->current_thread = current_task;
/* Nuke the old tasks */
rtos_free_threadlist(rtos);
/* One check if task switching has started ... */
start_called = 0;
ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_START_CALLED].address,
&start_called);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to load start_called");
return ret;
}
if (!rtos->current_thread || !num_tasks || !start_called) {
num_tasks++;
rtos->thread_details = malloc(
sizeof(struct thread_detail) * num_tasks);
rtos->thread_details->threadid = 1;
rtos->thread_details->exists = true;
rtos->thread_details->extra_info_str = NULL;
rtos->thread_details->thread_name_str = strdup("Current Execution");
if (!num_tasks || !start_called) {
rtos->thread_count = 1;
return ERROR_OK;
}
} else {
/* create space for new thread details */
rtos->thread_details = malloc(
sizeof(struct thread_detail) * num_tasks);
}
tasks_enabled = 0;
ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_TASKS_ENABLED].address,
&tasks_enabled);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to load tasks_enabled");
return ret;
}
tasks_ready = 0;
ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_TASKS_READY].address,
&tasks_ready);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to load tasks_ready");
return ret;
}
thread_ptr = rtos->symbols[CHROMIUM_EC_VAL_TASKS].address;
tasks_found = 0;
for (t = 0; t < CROS_EC_MAX_TASKS; t++) {
if (!(tasks_enabled & BIT(t)))
continue;
if (thread_ptr == current_task)
rtos->current_thread = thread_ptr;
rtos->thread_details[tasks_found].threadid = thread_ptr;
ret = target_read_u32(rtos->target,
rtos->symbols[CHROMIUM_EC_VAL_TASK_NAMES].address +
params->ptr_size * t, &name_ptr);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to read name_ptr");
return ret;
}
/* read name buffer */
ret = target_read_buffer(rtos->target, name_ptr, CROS_EC_MAX_NAME,
(uint8_t *)thread_str_buf);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to read task name");
return ret;
}
/* sanitize string, gdb chokes on "<< idle >>" */
if (thread_str_buf[CROS_EC_MAX_NAME - 1] != '\0')
thread_str_buf[CROS_EC_MAX_NAME - 1] = '\0';
if (!strncmp(thread_str_buf, CROS_EC_IDLE_STRING, CROS_EC_MAX_NAME))
rtos->thread_details[tasks_found].thread_name_str = strdup("IDLE");
else
rtos->thread_details[tasks_found].thread_name_str = strdup(thread_str_buf);
events = 0;
ret = target_read_u32(rtos->target,
thread_ptr + params->task_offset_events,
&events);
if (ret != ERROR_OK)
LOG_ERROR("Failed to get task %d's events", t);
/* this is a bit kludgy but will do for now */
ret = target_read_buffer(rtos->target,
thread_ptr + params->task_offset_runtime,
sizeof(runtime_buf), runtime_buf);
if (ret != ERROR_OK)
LOG_ERROR("Failed to get task %d's runtime", t);
runtime = target_buffer_get_u64(rtos->target, runtime_buf);
/* Priority is simply the position in the array */
if (thread_ptr == current_task)
snprintf(thread_str_buf, sizeof(thread_str_buf),
"State: Running, Priority: %u, Events: %" PRIx32 ", Runtime: %" PRIu64 "\n",
t, events, runtime);
else
snprintf(thread_str_buf, sizeof(thread_str_buf),
"State: %s, Priority: %u, Events: %" PRIx32 ", Runtime: %" PRIu64 "\n",
tasks_ready & BIT(t) ? "Ready" : "Waiting", t,
events, runtime);
rtos->thread_details[tasks_found].extra_info_str = strdup(thread_str_buf);
rtos->thread_details[tasks_found].exists = true;
thread_ptr += params->task_offset_next;
tasks_found++;
}
rtos->thread_count = tasks_found;
return ERROR_OK;
}
static int chromium_ec_get_thread_reg_list(struct rtos *rtos,
threadid_t threadid,
struct rtos_reg **reg_list,
int *num_regs)
{
struct chromium_ec_params *params = rtos->rtos_specific_params;
uint32_t stack_ptr = 0;
int ret, t;
for (t = 0; t < rtos->thread_count; t++)
if (threadid == rtos->thread_details[t].threadid)
break;
/* if we didn't find threadid, bail */
if (t == rtos->thread_count)
return ERROR_FAIL;
ret = target_read_u32(rtos->target,
rtos->symbols[CHROMIUM_EC_VAL_TASKS].address +
params->task_offset_next * t,
&stack_ptr);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to load TCB");
return ret;
}
return rtos_generic_stack_read(rtos->target, params->stacking,
stack_ptr, reg_list, num_regs);
}
static int chromium_ec_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
{
size_t s;
*symbol_list = calloc(ARRAY_SIZE(chromium_ec_symbol_list),
sizeof(struct symbol_table_elem));
if (!(*symbol_list)) {
LOG_ERROR("Chromium-EC: out of memory");
return ERROR_FAIL;
}
for (s = 0; s < ARRAY_SIZE(chromium_ec_symbol_list); s++)
(*symbol_list)[s].symbol_name = chromium_ec_symbol_list[s];
return ERROR_OK;
}
const struct rtos_type chromium_ec_rtos = {
.name = "Chromium-EC",
.detect_rtos = chromium_ec_detect_rtos,
.create = chromium_ec_create,
.update_threads = chromium_ec_update_threads,
.get_thread_reg_list = chromium_ec_get_thread_reg_list,
.get_symbol_list_to_lookup = chromium_ec_get_symbol_list_to_lookup,
};