1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <SEGGER_SYSVIEW.h>
9 #include <ksched.h>
10 
11 extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
12 
13 #if CONFIG_THREAD_MAX_NAME_LEN
14 #define THREAD_NAME_LEN CONFIG_THREAD_MAX_NAME_LEN
15 #else
16 #define THREAD_NAME_LEN 20
17 #endif
18 
19 
set_thread_name(char * name,struct k_thread * thread)20 static void set_thread_name(char *name, struct k_thread *thread)
21 {
22 	const char *tname = k_thread_name_get(thread);
23 
24 	if (tname != NULL && tname[0] != '\0') {
25 		memcpy(name, tname, THREAD_NAME_LEN);
26 		name[THREAD_NAME_LEN - 1] = '\0';
27 	} else {
28 		snprintk(name, THREAD_NAME_LEN, "T%pE%p",
29 		thread, &thread->entry);
30 	}
31 }
32 
sys_trace_thread_info(struct k_thread * thread)33 void sys_trace_thread_info(struct k_thread *thread)
34 {
35 	char name[THREAD_NAME_LEN];
36 
37 	set_thread_name(name, thread);
38 
39 	SEGGER_SYSVIEW_TASKINFO Info;
40 
41 	Info.TaskID = (uint32_t)(uintptr_t)thread;
42 	Info.sName = name;
43 	Info.Prio = thread->base.prio;
44 	Info.StackBase = thread->stack_info.size;
45 	Info.StackSize = thread->stack_info.start;
46 	SEGGER_SYSVIEW_SendTaskInfo(&Info);
47 }
48 
49 
cbSendSystemDesc(void)50 static void cbSendSystemDesc(void)
51 {
52 	SEGGER_SYSVIEW_SendSysDesc("N=" CONFIG_SEGGER_SYSVIEW_APP_NAME);
53 	SEGGER_SYSVIEW_SendSysDesc("D=" CONFIG_BOARD " "
54 				   CONFIG_SOC_SERIES " " CONFIG_ARCH);
55 	SEGGER_SYSVIEW_SendSysDesc("O=Zephyr");
56 }
57 
send_task_list_cb(void)58 static void send_task_list_cb(void)
59 {
60 	struct k_thread *thread;
61 
62 	for (thread = _kernel.threads; thread; thread = thread->next_thread) {
63 		char name[THREAD_NAME_LEN];
64 
65 		if (z_is_idle_thread_object(thread)) {
66 			continue;
67 		}
68 
69 		set_thread_name(name, thread);
70 
71 		SEGGER_SYSVIEW_SendTaskInfo(&(SEGGER_SYSVIEW_TASKINFO) {
72 			.TaskID = (uint32_t)(uintptr_t)thread,
73 			.sName = name,
74 			.StackSize = thread->stack_info.size,
75 			.StackBase = thread->stack_info.start,
76 			.Prio = thread->base.prio,
77 		});
78 	}
79 }
80 
81 
get_time_cb(void)82 static U64 get_time_cb(void)
83 {
84 	return (U64)k_cycle_get_32();
85 }
86 
87 
88 const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI = {
89 	get_time_cb,
90 	send_task_list_cb,
91 };
92 
93 
94 
SEGGER_SYSVIEW_Conf(void)95 void SEGGER_SYSVIEW_Conf(void)
96 {
97 	SEGGER_SYSVIEW_Init(sys_clock_hw_cycles_per_sec(),
98 			    sys_clock_hw_cycles_per_sec(),
99 			    &SYSVIEW_X_OS_TraceAPI, cbSendSystemDesc);
100 #if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_sram), okay)
101 	SEGGER_SYSVIEW_SetRAMBase(DT_REG_ADDR(DT_CHOSEN(zephyr_sram)));
102 #else
103 	/* Setting RAMBase is just an optimization: this value is subtracted
104 	 * from all pointers in order to save bandwidth.  It's not an error
105 	 * if a platform does not set this value.
106 	 */
107 #endif
108 }
109