commit 3da1267680504222bfe604c976332c2359d094b5
Author: Thomas Schöpping <tschoepp@cit-ec.uni-bielefeld.de>
Date:   Mon Jan 20 12:10:15 2020 +0100

    Introduced a new system shell command 'module:spuload' to read out CPU load

diff --git a/core/inc/aos_shell.h b/core/inc/aos_shell.h
index 4765782..c036ad9 100644
--- a/core/inc/aos_shell.h
+++ b/core/inc/aos_shell.h
@@ -35,8 +35,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 /* CONSTANTS                                                                  */
 /******************************************************************************/
 
-
-
 /**
  * @brief   Shell event flag that is emitted when the thread starts.
  */
@@ -242,6 +240,15 @@ typedef struct aos_shell {
    */
   thread_t* thread;
 
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+
+  /**
+   * @brief   Name of the shell and the associated thread.
+   */
+  const char* name;
+
+#endif /* (CH_CFG_USE_REGISTRY == TRUE) */
+
   /**
    * @brief   Event source.
    */
@@ -333,7 +340,7 @@ typedef struct aos_shell {
 #if defined(__cplusplus)
 extern "C" {
 #endif /* defined(__cplusplus) */
-  void aosShellInit(aos_shell_t* shell, const char* prompt, char inbuf[], size_t entries, size_t linewidth, size_t numargs);
+  void aosShellInit(aos_shell_t* shell, const char* name, const char* prompt, char inbuf[], size_t entries, size_t linewidth, size_t numargs);
   void aosShellStreamInit(AosShellStream* stream);
   void aosShellChannelInit(AosShellChannel* channel, BaseAsynchronousChannel* asyncchannel);
   aos_status_t aosShellAddCommand(aos_shell_t* shell, aos_shellcommand_t* cmd);
diff --git a/core/src/aos_main.cpp b/core/src/aos_main.cpp
index d7510e7..ad1ee77 100644
--- a/core/src/aos_main.cpp
+++ b/core/src/aos_main.cpp
@@ -78,6 +78,15 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 /* LOCAL VARIABLES                                                            */
 /******************************************************************************/
 
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+
+/**
+ * @brief   Name of the main thread.
+ */
+static const char _threadName[] = "control (main)";
+
+#endif /* (CH_CFG_USE_REGISTRY == TRUE) */
+
 /**
  * @brief   Listener object for GPIO events.
  */
@@ -269,6 +278,9 @@ int main(void)
 #if defined(MODULE_INIT_KERNEL_EXTRA)
   MODULE_INIT_KERNEL_EXTRA();
 #endif /* defined(MODULE_INIT_KERNEL_EXTRA) */
+#if (CH_CFG_USE_REGISTRY == TRUE)
+  currp->name = _threadName;
+#endif /* (CH_CFG_USE_REGISTRY == TRUE) */
 
   // AMiRo-OS, additional interrupts and custom OS additions (if any)
 #if (AMIROOS_CFG_SHELL_ENABLE == true)
diff --git a/core/src/aos_shell.c b/core/src/aos_shell.c
index 9db62b8..1b6a752 100644
--- a/core/src/aos_shell.c
+++ b/core/src/aos_shell.c
@@ -1838,13 +1838,14 @@ static size_t _parseArguments(aos_shell_t* shell, char* str, char** argbuf)
  * @brief   Initializes a shell object with the specified parameters.
  *
  * @param[in,out] shell           Pointer to the shell object to be initialized.
+ * @param[in]     name            Name of the shell thread (may be NULL).
  * @param[in]     prompt          Prompt line to print (NULL = use default prompt).
  * @param[in]     inbuf           Two dimensional input buffer.
  * @param[in]     entries         Number of entries in the input buffer (1st dimension).
  * @param[in]     linewidth       Length of each entry in the input buffer (2nd dimension).
  * @param[in]     numargs         Maximum number of arguments (defines size of internal buffer).
  */
-void aosShellInit(aos_shell_t* shell, const char* prompt, char inbuf[], size_t entries, size_t linewidth, size_t numargs)
+void aosShellInit(aos_shell_t* shell, const char* name, const char* prompt, char inbuf[], size_t entries, size_t linewidth, size_t numargs)
 {
   aosDbgCheck(shell != NULL);
   aosDbgCheck(inbuf != NULL);
@@ -1854,6 +1855,11 @@ void aosShellInit(aos_shell_t* shell, const char* prompt, char inbuf[], size_t e
 
   // set parameters
   shell->thread = NULL;
+#if (CH_CFG_USE_REGISTRY == TRUE)
+  shell->name = name;
+#else /* (CH_CFG_USE_REGISTRY == TRUE) */
+  (void)name;
+#endif /* (CH_CFG_USE_REGISTRY == TRUE) */
   chEvtObjectInit(&shell->eventSource);
   aosShellStreamInit(&shell->stream);
   shell->prompt = prompt;
@@ -2179,6 +2185,9 @@ void aosShellThread(void* shell)
   aos_shellcommand_t* cmd;
 
   // initialize variables and buffers
+#if (CH_CFG_USE_REGISTRY == TRUE)
+  currp->name = ((aos_shell_t*)shell)->name;
+#endif /* (CH_CFG_USE_REGISTRY == TRUE) */
   rdata.input.length = 0;
   rdata.input.cursorpos = 0;
   memset(rdata.input.escseq, '\0', AOS_SHELL_ESCSEQUENCE_LENGTH * sizeof(char));
diff --git a/core/src/aos_system.c b/core/src/aos_system.c
index 67f20af..c04c1cd 100644
--- a/core/src/aos_system.c
+++ b/core/src/aos_system.c
@@ -88,6 +88,9 @@ aos_system_t aos;
 static int _shellcmd_configcb(BaseSequentialStream* stream, int argc, char* argv[]);
 static int _shellcmd_infocb(BaseSequentialStream* stream, int argc, char* argv[]);
 static int _shellcmd_shutdowncb(BaseSequentialStream* stream, int argc, char* argv[]);
+#if ((CH_CFG_USE_REGISTRY == TRUE) && (CH_DBG_STATISTICS == TRUE)) || defined(__DOXYGEN__)
+static int _shellcmd_cpuloadcb(BaseSequentialStream* stream, int argc, char* argv[]);
+#endif /* (CH_CFG_USE_REGISTRY == TRUE) && (CH_DBG_STATISTICS == TRUE) */
 #if (AMIROOS_CFG_TESTS_ENABLE == true) || defined(__DOXYGEN__)
 static int _shellcmd_kerneltestcb(BaseSequentialStream* stream, int argc, char* argv[]);
 #endif /* (AMIROOS_CFG_TESTS_ENABLE == true) */
@@ -111,6 +114,11 @@ static systime_t _synctime;
 #if (AMIROOS_CFG_SHELL_ENABLE == true) || defined(__DOXYGEN__)
 
 /**
+ * @brief   System shell name.
+ */
+static const char _shell_name[] = "system shell";
+
+/**
  * @brief   Shell thread working area.
  */
 static THD_WORKING_AREA(_shell_wa, AMIROOS_CFG_SHELL_STACKSIZE);
@@ -139,10 +147,19 @@ static AOS_SHELL_COMMAND(_shellcmd_shutdown, "system:shutdown", _shellcmd_shutdo
 static AOS_SHELL_COMMAND(_shellcmd_shutdown, "module:shutdown", _shellcmd_shutdowncb);
 #endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
 
+#if ((CH_CFG_USE_REGISTRY == TRUE) && (CH_DBG_STATISTICS == TRUE)) || defined(__DOXYGEN__)
+
+/**
+ * @brief   Shell command to read out CPU load.
+ */
+static AOS_SHELL_COMMAND(_shellcmd_cpuload, "module:cpuload", _shellcmd_cpuloadcb);
+
+#endif /* (CH_CFG_USE_REGISTRY == TRUE) && (CH_DBG_STATISTICS == TRUE) */
+
 #if (AMIROOS_CFG_TESTS_ENABLE == true) || defined(__DOXYGEN__)
 
 /**
- * @brief   Shell kommand to run a test of the ChibiOS/RT kernel.
+ * @brief   Shell command to run a test of the ChibiOS/RT kernel.
  */
 static AOS_SHELL_COMMAND(_shellcmd_kerneltest, "kernel:test", _shellcmd_kerneltestcb);
 
@@ -238,6 +255,7 @@ static void _printSystemInfo(BaseSequentialStream* stream)
   _printSystemInfoLine(stream, "Core Variant", SYSTEM_INFO_NAMEWIDTH, "%s", PORT_CORE_VARIANT_NAME);
 #endif /* defined(PORT_CORE_VARIANT_NAME) */
   _printSystemInfoLine(stream, "Architecture", SYSTEM_INFO_NAMEWIDTH, "%s", PORT_ARCHITECTURE_NAME);
+  _printSystemInfoLine(stream, "Core Frequency", SYSTEM_INFO_NAMEWIDTH, "%u MHz", SystemCoreClock / 1000000);
   _printSystemInfoSeparator(stream, '-', SYSTEM_INFO_WIDTH);
 #if (AMIROOS_CFG_SSSP_ENABLE == true)
   _printSystemInfoLine(stream, "AMiRo-OS" , SYSTEM_INFO_NAMEWIDTH, "%u.%u.%u %s (SSSP %u.%u)", AMIROOS_VERSION_MAJOR, AMIROOS_VERSION_MINOR, AMIROOS_VERSION_PATCH, AMIROOS_RELEASE_TYPE, AOS_SSSP_VERSION_MAJOR, AOS_SSSP_VERSION_MINOR);
@@ -622,6 +640,67 @@ static int _shellcmd_shutdowncb(BaseSequentialStream* stream, int argc, char* ar
 #endif /* (AMIROOS_CFG_BOOTLOADER == X) */
 }
 
+#if ((CH_CFG_USE_REGISTRY == TRUE) && (CH_DBG_STATISTICS == TRUE)) || defined(__DOXYGEN__)
+
+/**
+ * @brief   Callback function for the module:cpuload shell command.
+ *
+ * @param[in] stream    The I/O stream to use.
+ * @param[in] argc      Number of arguments.
+ * @param[in] argv      List of pointers to arguments.
+ *
+ * @return      An exit status.
+ */
+static int _shellcmd_cpuloadcb(BaseSequentialStream* stream, int argc, char* argv[])
+{
+  aosDbgCheck(stream != NULL);
+
+  (void)argc;
+  (void)argv;
+
+  // local variables
+  rttime_t sum = 0;
+  thread_t* thd = chRegFirstThread();
+
+  // accumulate system load
+  do {
+    sum += thd->stats.cumulative;
+    thd = chRegNextThread(thd);
+  } while (thd);
+  sum += ch.kernel_stats.m_crit_thd.cumulative + ch.kernel_stats.m_crit_isr.cumulative;
+
+  // calculate and retreive cpu load per thread
+  chprintf(stream, "threads & critical zones:\n");
+  thd = chRegFirstThread();
+  do {
+    chprintf(stream, "\t%22s: %6.2f%%\n",
+             (thd->name != NULL) ? thd->name : "<unnamed thread>",
+             (float)thd->stats.cumulative / (float)sum * 100.f);
+    thd = chRegNextThread(thd);
+  } while (thd);
+  chprintf(stream, "\t%22s: %6.2f%%\n",
+           "thread critical zones",
+           (float)ch.kernel_stats.m_crit_thd.cumulative / (float)sum * 100.f);
+  chprintf(stream, "\t%22s: %6.2f%%\n",
+           "ISR critical zones",
+           (float)ch.kernel_stats.m_crit_isr.cumulative / (float)sum * 100.f);
+
+  // retreive further real-time statistics
+  chprintf(stream, "\nworst critical zones:\n");
+  chprintf(stream, "\tthreads: %uus (%u clocks @ %uMHz)\n",
+           RTC2US(SystemCoreClock, ch.kernel_stats.m_crit_thd.worst),
+           ch.kernel_stats.m_crit_thd.worst,
+           SystemCoreClock / 1000000);
+  chprintf(stream, "\t   ISRs: %uus (%u clocks @ %uMHz)\n",
+           RTC2US(SystemCoreClock, ch.kernel_stats.m_crit_isr.worst),
+           ch.kernel_stats.m_crit_isr.worst,
+           SystemCoreClock / 1000000);
+
+  return 0;
+}
+
+#endif /* (CH_CFG_USE_REGISTRY == TRUE) && (CH_DBG_STATISTICS == TRUE) */
+
 #if (AMIROOS_CFG_TESTS_ENABLE == true) || defined(__DOXYGEN__)
 
 /**
@@ -750,6 +829,7 @@ void aosSysInit(const char* shellPrompt)
 
   /* init shell */
   aosShellInit(&aos.shell,
+               _shell_name,
                shellPrompt,
                _shell_buffer,
                SYSTEM_SHELL_BUFFERENTRIES,
@@ -759,6 +839,9 @@ void aosSysInit(const char* shellPrompt)
   aosShellAddCommand(&aos.shell, &_shellcmd_config);
   aosShellAddCommand(&aos.shell, &_shellcmd_info);
   aosShellAddCommand(&aos.shell, &_shellcmd_shutdown);
+#if ((CH_CFG_USE_REGISTRY == TRUE) && (CH_DBG_STATISTICS == TRUE)) || defined(__DOXYGEN__)
+  aosShellAddCommand(&aos.shell, &_shellcmd_cpuload);
+#endif /* (CH_CFG_USE_REGISTRY == TRUE) && (CH_DBG_STATISTICS == TRUE) */
 #if (AMIROOS_CFG_TESTS_ENABLE == true)
   aosShellAddCommand(&aos.shell, &_shellcmd_kerneltest);
 #endif /* (AMIROOS_CFG_TESTS_ENABLE == true) */
diff --git a/modules/aos_chconf.h b/modules/aos_chconf.h
index 53ca1cc..53784ae 100644
--- a/modules/aos_chconf.h
+++ b/modules/aos_chconf.h
@@ -492,7 +492,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * @note    The default is @p FALSE.
  */
 #if !defined(CH_DBG_STATISTICS)
-#if ((CH_CFG_USE_TM == TRUE) && (AMIROOS_CFG_DBG == true)) || defined(__DOXYGEN__)
+#if ((CH_CFG_USE_TM == TRUE) && ((AMIROOS_CFG_DBG == true) || AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__)
   #define CH_DBG_STATISTICS                 TRUE
 #else
   #define CH_DBG_STATISTICS                 FALSE
