Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
rtos_mon_arch.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016 Gautier Hattenberger <gautier.hattenberger@enac.fr>
3 * 2020 Gautier Hattenberger, Alexandre Bustico
4 *
5 * This file is part of paparazzi
6 *
7 * paparazzi is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * paparazzi is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with paparazzi; see the file COPYING. If not, see
19 * <http://www.gnu.org/licenses/>.
20 */
30#include <ch.h>
31
32#if !CH_DBG_STATISTICS
33#error CH_DBG_STATISTICS should be defined to TRUE to use this monitoring tool
34#endif
35
37
38static uint16_t get_stack_free(const thread_t *tp);
39
40#if USE_SHELL
41#include "modules/core/shell.h"
42#include "mcu_periph/sys_time.h"
43#include "printf.h"
44#include "string.h"
45
46typedef struct _ThreadCpuInfo {
48 float cpu[RTOS_MON_MAX_THREADS];
49 float totalTicks;
50 float totalISRTicks;
52
53
55{
56 const thread_t *tp = chRegFirstThread();
57 uint32_t idx = 0;
58
59 ti->totalTicks = 0;
60 do {
61 ti->ticks[idx] = (float) tp->stats.cumulative;
62 ti->totalTicks += ti->ticks[idx];
64 idx++;
65 } while ((tp != NULL) && (idx < RTOS_MON_MAX_THREADS));
66 ti->totalISRTicks = ch0.kernel_stats.m_crit_isr.cumulative;
67 ti->totalTicks += ti->totalISRTicks;
69 idx = 0;
70 do {
71 ti->cpu[idx] = (ti->ticks[idx] * 100.f) / ti->totalTicks;
73 idx++;
74 } while ((tp != NULL) && (idx < RTOS_MON_MAX_THREADS));
75}
76
77static float stampThreadGetCpuPercent(const ThreadCpuInfo *ti, const uint32_t idx)
78{
80 return -1.f;
81 }
82
83 return ti->cpu[idx];
84}
85
86static float stampISRGetCpuPercent(const ThreadCpuInfo *ti)
87{
88 return ti->totalISRTicks * 100.0f / ti->totalTicks;
89}
90
91static void cmd_threads(BaseSequentialStream *lchp, int argc, const char *const argv[])
92{
93 static const char *states[] = {CH_STATE_NAMES};
95 (void)argv;
96 (void)argc;
97 float totalTicks = 0;
98 float idleTicks = 0;
99
101 .ticks = {[0 ... RTOS_MON_MAX_THREADS - 1] = 0.f},
102 .cpu = {[0 ... RTOS_MON_MAX_THREADS - 1] = -1.f},
103 .totalTicks = 0.f,
104 .totalISRTicks = 0.f
105 };
106
108
109 chprintf(lchp, " addr stack frestk prio refs state time \t percent name\r\n");
110 uint32_t idx = 0;
111 do {
112 chprintf(lchp, "%.8lx %.8lx %6lu %4lu %4lu %9s %9lu %.2f%% \t%s\r\n",
113 (uint32_t)tp, (uint32_t)tp->ctx.sp,
115 (uint32_t)tp->hdr.pqueue.prio, (uint32_t)(tp->refs - 1),
116 states[tp->state],
117 (uint32_t)RTC2MS(STM32_SYSCLK, tp->stats.cumulative),
120
121 totalTicks += (float)tp->stats.cumulative;
122 if (strcmp(chRegGetThreadNameX(tp), "idle") == 0) {
123 idleTicks = (float)tp->stats.cumulative;
124 }
126 idx++;
127 } while (tp != NULL);
128
129 totalTicks += ch0.kernel_stats.m_crit_isr.cumulative;
130 const float idlePercent = (idleTicks * 100.f) / totalTicks;
131 const float cpuPercent = 100.f - idlePercent;
132 chprintf(lchp, "Interrupt Service Routine \t\t %9lu %.2f%% \tISR\r\n",
133 (uint32_t)RTC2MS(STM32_SYSCLK, threadCpuInfo.totalISRTicks),
135 chprintf(lchp, "\r\ncpu load = %.2f%%\r\n", cpuPercent);
136}
137
138static void cmd_rtos_mon(shell_stream_t *sh, int argc, const char *const argv[])
139{
140 (void) argv;
141 if (argc > 0) {
142 chprintf(sh, "Usage: rtos_mon\r\n");
143 return;
144 }
145
146 chprintf(sh, "Data reported in the RTOS_MON message:\r\n");
147 chprintf(sh, " core free mem: %u\r\n", rtos_mon.core_free_memory);
148 chprintf(sh, " heap free mem: %u\r\n", rtos_mon.heap_free_memory);
149 chprintf(sh, " heap fragments: %u\r\n", rtos_mon.heap_fragments);
150 chprintf(sh, " heap largest: %u\r\n", rtos_mon.heap_largest);
151 chprintf(sh, " CPU load: %d \%\r\n", rtos_mon.cpu_load);
152 chprintf(sh, " number of threads: %d\r\n", rtos_mon.thread_counter);
153 chprintf(sh, " thread names: %s\r\n", rtos_mon.thread_names);
154 for (int i = 0; i < rtos_mon.thread_counter; i++) {
155 chprintf(sh, " thread %d load: %0.1f, free stack: %d\r\n", i,
156 (float)rtos_mon.thread_load[i] / 10.f, rtos_mon.thread_free_stack[i]);
157 }
158 chprintf(sh, " CPU time: %.2f\r\n", rtos_mon.cpu_time);
159}
160#endif
161
163{
164#if USE_SHELL
165 shell_add_entry("rtos_mon", cmd_rtos_mon);
166 shell_add_entry("threads", cmd_threads);
167#endif
168}
169
170// Fill data structure
172{
173 int i;
178
184
185 // loop threads to find idle thread
186 // store info on other threads
187 thread_t *tp;
188 float idle_counter = 0.f;
189 float sum = 0.f;
192 do {
193 // add beginning of thread name to buffer
194 for (i = 0; i < RTOS_MON_NAME_LEN - 1 && tp->name[i] != '\0'; i++) {
196 }
198
199 // store free stack for this thread
201
202 // store time spend in thread
203 thread_p_time[rtos_mon.thread_counter] = tp->stats.cumulative;
204 sum += (float)(tp->stats.cumulative);
205
206 // if current thread is 'idle' thread, store its value separately
207 if (tp == chSysGetIdleThreadX()) {
208 idle_counter = (float)tp->stats.cumulative;
209 }
210 // get next thread
212 // increment thread counter
215 // sum the time spent in ISR
216 sum += ch0.kernel_stats.m_crit_isr.cumulative;
217 // store individual thread load (as centi-percent integer, i.e. (th_time/sum)*10*100)
218 for (i = 0; i < rtos_mon.thread_counter; i ++) {
219 rtos_mon.thread_load[i] = (uint16_t)(1000.f * (float)thread_p_time[i] / sum);
220 }
221
222 // assume we call the counter once a second
223 // so the difference in seconds is always one
224 // NOTE: not perfectly precise, +-5% on average so take it into consideration
225 rtos_mon.cpu_load = (uint8_t)((1.f - (idle_counter / sum)) * 100.f);
226}
227
229{
230 int32_t index = 0;
231 extern const uint8_t __ram0_end__;
232 unsigned long long *stkAdr = (unsigned long long *)((uint8_t *) tp->wabase);
233 while ((stkAdr[index] == 0x5555555555555555) && (((uint8_t *) & (stkAdr[index])) < &__ram0_end__)) {
234 index++;
235 }
236 const int32_t freeBytes = index * (int32_t) sizeof(long long);
237 return (uint16_t)freeBytes;
238}
239
static uint32_t thread_p_time[RTOS_MON_MAX_THREADS]
void rtos_mon_periodic_arch(void)
void rtos_mon_init_arch(void)
static uint16_t get_stack_free(const thread_t *tp)
static struct nodeState states[UWB_SERIAL_COMM_DIST_NUM_NODES]
int ticks
Definition gps_sirf.c:193
void chprintf(BaseSequentialStream *lchp, const char *fmt,...)
Definition printf.c:395
uint16_t foo
Definition main_demo5.c:58
static uint32_t idx
Mini printf-like functionality.
struct rtos_monitoring rtos_mon
Definition rtos_mon.c:30
void shell_add_entry(char *cmd_name, shell_cmd_t *cmd)
Add dynamic entry.
Definition shell_arch.c:92
BaseSequentialStream shell_stream_t
Definition shell_arch.h:31
System monitoring for RTOS targets return cpu load, average exec time, ...
uint8_t cpu_load
global CPU/MCU load in %
char thread_names[RTOS_MON_THREAD_NAMES+1]
string of thread names / identifiers
uint32_t core_free_memory
core free memory in bytes
uint16_t thread_free_stack[RTOS_MON_MAX_THREADS]
individual thread free stack in bytes
uint32_t heap_free_memory
Total fragmented free memory in the heap.
uint16_t thread_load[RTOS_MON_MAX_THREADS]
individual thread load in centi-percent (10*%)
uint8_t thread_name_idx
length of the string in thread_names buffer
uint8_t thread_counter
number of threads
#define RTOS_MON_MAX_THREADS
uint32_t heap_fragments
Number of fragments in the heap.
#define RTOS_MON_NAME_LEN
uint32_t heap_largest
Largest free block in the heap.
Architecture independent timing functions.
Implementation of system time functions for ChibiOS arch.
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
int int32_t
Typedef defining 32 bit int type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.