blob: 2914bba2b2bd4ddbf0c9da2c791761777d1e767d [file] [log] [blame]
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <kernel_structs.h>
#include <init.h>
#include <ksched.h>
#include <SEGGER_SYSVIEW.h>
#include <Global.h>
#include "SEGGER_SYSVIEW_Zephyr.h"
#if CONFIG_THREAD_MAX_NAME_LEN
#define THREAD_NAME_LEN CONFIG_THREAD_MAX_NAME_LEN
#else
#define THREAD_NAME_LEN 20
#endif
static uint32_t interrupt;
uint32_t sysview_get_timestamp(void)
{
return k_cycle_get_32();
}
uint32_t sysview_get_interrupt(void)
{
return interrupt;
}
void sys_trace_thread_switched_in(void)
{
struct k_thread *thread;
thread = k_current_get();
if (z_is_idle_thread_object(thread)) {
SEGGER_SYSVIEW_OnIdle();
} else {
SEGGER_SYSVIEW_OnTaskStartExec((uint32_t)(uintptr_t)thread);
}
}
void sys_trace_thread_switched_out(void)
{
SEGGER_SYSVIEW_OnTaskStopExec();
}
void sys_trace_isr_enter(void)
{
SEGGER_SYSVIEW_RecordEnterISR();
}
void sys_trace_isr_exit(void)
{
SEGGER_SYSVIEW_RecordExitISR();
}
void sys_trace_isr_exit_to_scheduler(void)
{
SEGGER_SYSVIEW_RecordExitISRToScheduler();
}
void sys_trace_idle(void)
{
SEGGER_SYSVIEW_OnIdle();
}
void sys_trace_semaphore_init(struct k_sem *sem)
{
SEGGER_SYSVIEW_RecordU32(
SYS_TRACE_ID_SEMA_INIT, (uint32_t)(uintptr_t)sem);
}
void sys_trace_semaphore_take(struct k_sem *sem)
{
SEGGER_SYSVIEW_RecordU32(
SYS_TRACE_ID_SEMA_TAKE, (uint32_t)(uintptr_t)sem);
}
void sys_trace_semaphore_give(struct k_sem *sem)
{
SEGGER_SYSVIEW_RecordU32(
SYS_TRACE_ID_SEMA_GIVE, (uint32_t)(uintptr_t)sem);
}
void sys_trace_mutex_init(struct k_mutex *mutex)
{
SEGGER_SYSVIEW_RecordU32(
SYS_TRACE_ID_MUTEX_INIT, (uint32_t)(uintptr_t)mutex);
}
void sys_trace_mutex_lock(struct k_mutex *mutex)
{
SEGGER_SYSVIEW_RecordU32(
SYS_TRACE_ID_MUTEX_LOCK, (uint32_t)(uintptr_t)mutex);
}
void sys_trace_mutex_unlock(struct k_mutex *mutex)
{
SEGGER_SYSVIEW_RecordU32(
SYS_TRACE_ID_MUTEX_UNLOCK, (uint32_t)(uintptr_t)mutex);
}
static void set_thread_name(char *name, struct k_thread *thread)
{
const char *tname = k_thread_name_get(thread);
if (tname != NULL && tname[0] != '\0') {
memcpy(name, tname, THREAD_NAME_LEN);
name[THREAD_NAME_LEN - 1] = '\0';
} else {
snprintk(name, THREAD_NAME_LEN, "T%pE%p",
thread, &thread->entry);
}
}
void sys_trace_thread_info(struct k_thread *thread)
{
char name[THREAD_NAME_LEN];
set_thread_name(name, thread);
SEGGER_SYSVIEW_TASKINFO Info;
Info.TaskID = (uint32_t)(uintptr_t)thread;
Info.sName = name;
Info.Prio = thread->base.prio;
Info.StackBase = thread->stack_info.size;
Info.StackSize = thread->stack_info.start;
SEGGER_SYSVIEW_SendTaskInfo(&Info);
}
static void send_task_list_cb(void)
{
struct k_thread *thread;
for (thread = _kernel.threads; thread; thread = thread->next_thread) {
char name[THREAD_NAME_LEN];
if (z_is_idle_thread_object(thread)) {
continue;
}
set_thread_name(name, thread);
SEGGER_SYSVIEW_SendTaskInfo(&(SEGGER_SYSVIEW_TASKINFO) {
.TaskID = (uint32_t)(uintptr_t)thread,
.sName = name,
.StackSize = thread->stack_info.size,
.StackBase = thread->stack_info.start,
.Prio = thread->base.prio,
});
}
}
static U64 get_time_cb(void)
{
return (U64)k_cycle_get_32();
}
const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI = {
get_time_cb,
send_task_list_cb,
};
static int sysview_init(const struct device *arg)
{
ARG_UNUSED(arg);
SEGGER_SYSVIEW_Conf();
if (IS_ENABLED(CONFIG_SEGGER_SYSTEMVIEW_BOOT_ENABLE)) {
SEGGER_SYSVIEW_Start();
}
return 0;
}
SYS_INIT(sysview_init, POST_KERNEL, 0);