Difference between revisions of "Zephyr"

From Wiki at Neela Nurseries
Jump to: navigation, search
m (^ Zephyr Kernel Timing)
m ()
Line 190: Line 190:
 
<!-- comentario -->
 
<!-- comentario -->
  
== <hr /> ==
+
== ----- ----- -----  ----- ----- -----  ----- ----- ----- ==
  
 
<!-- comentario -->
 
<!-- comentario -->

Revision as of 18:53, 16 November 2021

Zephyr RTOS Logger and Backend Features

Zephyr's thread_analyzer when not configured to dump reports to printk() instead sends thread data to LOG_INF(). Excerpt from Zephyr file `./zephyr/subsys/debug/thread_analyzer.c`:

 11 #include <kernel.h>
 12 #include <debug/thread_analyzer.h>
 13 #include <debug/stack.h>
 14 #include <kernel.h>
 15 #include <logging/log.h>
 16 #include <stdio.h>
 17 
 18 LOG_MODULE_REGISTER(thread_analyzer, CONFIG_THREAD_ANALYZER_LOG_LEVEL);
 19 
 20 #if IS_ENABLED(CONFIG_THREAD_ANALYZER_USE_PRINTK)
 21 #define THREAD_ANALYZER_PRINT(...) printk(__VA_ARGS__)
 22 #define THREAD_ANALYZER_FMT(str)   str "\n"
 23 #define THREAD_ANALYZER_VSTR(str)  (str)
 24 #else
 25 #define THREAD_ANALYZER_PRINT(...) LOG_INF(__VA_ARGS__)
 26 #define THREAD_ANALYZER_FMT(str)   str
 27 #define THREAD_ANALYZER_VSTR(str)  log_strdup(str)
 28 #endif

Zephyr macro `LOG_INF` is in turn defined:

ted@localhost:~/projects/zephyr-based/z4-sandbox-kionix-work/zephyr$ grep -nr LOG_INF ./* | grep define

./include/logging/log.h:61:#define LOG_INF(...)   Z_LOG(LOG_LEVEL_INF, __VA_ARGS__)

Define of Z_LOG:

ted@localhost:~/projects/zephyr-based/z4-sandbox-kionix-work/zephyr$ grep -nr 'Z_LOG[^_]' ./*

./include/logging/log_core.h:295:#define Z_LOG2(_level, _source, _dsource, ...) do { \
./include/logging/log_core.h:329:#define Z_LOG(_level, ...) \


$ grep -nr 'Z_LOG[^_]' ./*

$ vi ./include/logging/log_core.h

329 #define Z_LOG(_level, ...) \
330         Z_LOG2(_level, __log_current_const_data, __log_current_dynamic_data, __VA_ARGS__)


A Zephyr RTOS sample to check out:

`ted@localhost:~/projects/zephyr-based/z4-sandbox-kionix-work/zephyr/samples/subsys/logging/logger$`


^ To Create And To Name Zephyr Threads


^ Zephyr thread_analyzer_cb And Related

Zephyr 2.6.0's thread_analyzer_cb() routine gathers and populates a structure with all pertinent, reported run-time thread statistics. This is however a static routine so we cannot call it directly. Nor does it return the summary thread resource use data to its direct calling routine. There is yet hope, and to understand a path forward here excerpted is the definition of this important thread reporting routine from file `./zephyr/subsys/debug/thread_analyzer.c`:

 59 static void thread_analyze_cb(const struct k_thread *cthread, void *user_data)
 60 {
 61         struct k_thread *thread = (struct k_thread *)cthread;
 62 #ifdef CONFIG_THREAD_RUNTIME_STATS
 63         k_thread_runtime_stats_t rt_stats_all;
 64         k_thread_runtime_stats_t rt_stats_thread;
 65         int ret;
 66 #endif
 67         size_t size = thread->stack_info.size;
 68         thread_analyzer_cb cb = user_data;
 69         struct thread_analyzer_info info;
 70         char hexname[PTR_STR_MAXLEN + 1];
 71         const char *name;
 72         size_t unused;
 73         int err;
 74 
 75 
 76 
 77         name = k_thread_name_get((k_tid_t)thread);
 78         if (!name || name[0] == '\0') {
 79                 name = hexname;
 80                 snprintk(hexname, sizeof(hexname), "%p", (void *)thread);
 81         }
 82 
 83         err = k_thread_stack_space_get(thread, &unused);
 84         if (err) {
 85                 THREAD_ANALYZER_PRINT(
 86                         THREAD_ANALYZER_FMT(
 87                                 " %-20s: unable to get stack space (%d)"),
 88                         name, err);

 88                         name, err);
 89 
 90                 unused = 0;
 91         }
 92 
 93         info.name = name;
 94         info.stack_size = size;
 95         info.stack_used = size - unused;
 96 
 97 #ifdef CONFIG_THREAD_RUNTIME_STATS
 98         ret = 0;
 99 
100         if (k_thread_runtime_stats_get(thread, &rt_stats_thread) != 0) {
101                 ret++;
102         }
103 
104         if (k_thread_runtime_stats_all_get(&rt_stats_all) != 0) {
105                 ret++;
106         }
107         if (ret == 0) {
108                 info.utilization = (rt_stats_thread.execution_cycles * 100U) /
109                         rt_stats_all.execution_cycles;
110         }
111 #endif
112         cb(&info);
113 }

The routine which calls this is:

115 void thread_analyzer_run(thread_analyzer_cb cb)
116 {
117         if (IS_ENABLED(CONFIG_THREAD_ANALYZER_RUN_UNLOCKED)) {
118                 k_thread_foreach_unlocked(thread_analyze_cb, cb);
119         } else {
120                 k_thread_foreach(thread_analyze_cb, cb);
121         }
122 }

We should be able to directly call thread_analyzer_run(thread_analyzer_cb cb). If yes, and if we can learn how &info is defined, we should be able to redirect thread_analyzer reports to an arbitrary UART . . .


^ Z

ted@localhost:~/projects/zephyr-based/z4-sandbox-kionix-work/zephyr$ grep -nr 'struct thread_analyzer_info' ./*
./include/debug/thread_analyzer.h:23:struct thread_analyzer_info {
./include/debug/thread_analyzer.h:44:typedef void (*thread_analyzer_cb)(struct thread_analyzer_info *info);

Structure definition for &info passed to thread_analyzer_cb() function above:

/** @defgroup thread_analyzer Thread analyzer
 *  @brief Module for analyzing threads
 *
 *  This module implements functions and the configuration that simplifies
 *  thread analysis.
 *  @{
 */

struct thread_analyzer_info {
        /** The name of the thread or stringified address of the thread handle
         * if name is not set.
         */
        const char *name;
        /** The total size of the stack*/
        size_t stack_size;
        /** Stack size in used */
        size_t stack_used;

#ifdef CONFIG_THREAD_RUNTIME_STATS
        unsigned int utilization;
#endif
};


----- ----- ----- ----- ----- ----- ----- ----- -----

^ Zephyr Kernel Timing