rtos: Add RTOS task awareness for Chromium-EC

Add RTOS task awareness for Chromium-EC. Currently
only supports ARM Cortex-M0/M3/M4 based targets.

No new Clang Analyzer warnings.

Change-Id: Iea56fcb1be220e2437613922879b63d6e553703d
Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
Reviewed-on: http://openocd.zylin.com/4685
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
log_output
Moritz Fischer 2018-09-29 17:50:06 -07:00 committed by Matthias Welwarsky
parent d2fb461621
commit 731dc36a67
3 changed files with 390 additions and 0 deletions

View File

@ -12,6 +12,7 @@ noinst_LTLIBRARIES += %D%/librtos.la
%D%/eCos.c \
%D%/linux.c \
%D%/ChibiOS.c \
%D%/chromium-ec.c \
%D%/embKernel.c \
%D%/mqx.c \
%D%/uCOS-III.c \

387
src/rtos/chromium-ec.c Normal file
View File

@ -0,0 +1,387 @@
/*
* 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 positon 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(symbol_table_elem_t *symbol_list[])
{
size_t s;
*symbol_list = calloc(ARRAY_SIZE(chromium_ec_symbol_list),
sizeof(symbol_table_elem_t));
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,
};

View File

@ -32,6 +32,7 @@ extern struct rtos_type ThreadX_rtos;
extern struct rtos_type eCos_rtos;
extern struct rtos_type Linux_os;
extern struct rtos_type ChibiOS_rtos;
extern struct rtos_type chromium_ec_rtos;
extern struct rtos_type embKernel_rtos;
extern struct rtos_type mqx_rtos;
extern struct rtos_type uCOS_III_rtos;
@ -43,6 +44,7 @@ static struct rtos_type *rtos_types[] = {
&eCos_rtos,
&Linux_os,
&ChibiOS_rtos,
&chromium_ec_rtos,
&embKernel_rtos,
&mqx_rtos,
&uCOS_III_rtos,