samples/task_profiler: add RTC/counter support as timestamp

On Quark SE, using system timer as event timestamp creates
inconsistencies since the timer is handled by software in
timer_int_handler and tickless_idle_exit. So timestamp does not
reflect timing of certain events like timer IRQ.

This patch introduces the usage of RTC or AON counter as kernel
event logger timestamp

Change-Id: I070254446dd98dd448e119892c34abf12efca719
Signed-off-by: Fabrice Olivero <fabrice.olivero@intel.com>
This commit is contained in:
Fabrice Olivero 2016-05-17 13:51:44 +02:00 committed by Anas Nashif
commit 8a1c4e642b
5 changed files with 99 additions and 0 deletions

View file

@ -72,6 +72,9 @@ prof.log = profiler output file generated from Zephyr target (binary)
1) Enable KERNEL_EVENT_LOGGER
-----------------------------
1.1) Kernel event logger configuration
--------------------------------------
Edit project configuration file (e.g. $APP_BASE/prj.conf) and add the following
flags:
@ -108,6 +111,29 @@ If wanting to understand microkernel object usage and task bit handling,
recommended value is 6
Otherwise, task monitor can be disabled (to decrease logger ring buffer usage)
1.2) Kernel event logger timestamp
----------------------------------
By default, the kernel event logger is using the system timer for timestamping
events. As system timer may not work properly depending on platform, this timer
can be set at runtime using following flag:
$APP_BASE/prj.conf:
CONFIG_KERNEL_EVENT_LOGGER_CUSTOM_TIMESTAMP=y
In that case, the profiler will set the RTC as timestamp so RTC must be enabled
$APP_BASE/prj.conf:
CONFIG_RTC=y
In case the RTC cannot be used, profiler can support counters as well by
building application with the following way:
$APP_BASE/prj.conf:
CONFIG_COUNTER=y
Build command:
make BOARD=... PROFILER_USE_COUNTER=y
2) Enable UART flush [OPTIONAL]
-------------------------------
@ -240,6 +266,16 @@ make BOARD=... PROFILER_NO_SHELL_REGISTER=1
4) Build and flash project
--------------------------
Flags that can be used by the profiler
PROFILER_NO_SHELL_REGISTER: when profiler dynamic control is set, the profiler
won't set its own console handler. In that case the
profiler commands must be added to the application
console handler
PROFILER_USECOUNTER: in case custom timestamp is set for the kernel event
logger, the profiler will use RTC. This flag allows to
use a counter instead
5) Get prepared for collecting profiler data
--------------------------------------------

View file

@ -3,5 +3,8 @@ ccflags-y += -I${ZEPHYR_BASE}/include/drivers/
ifeq (${PROFILER_NO_SHELL_REGISTER},1)
ccflags-y += -DPROFILER_NO_SHELL_REGISTER
endif
ifeq (${PROFILER_USE_COUNTER},1)
ccflags-y += -DPROFILER_USE_COUNTER
endif
obj-y = profiler.o

View file

@ -167,16 +167,72 @@ struct shell_cmd commands[] = {
PROF_CMD,
{ NULL, NULL}
};
#endif /* PROFILER_SHELL */
#undef TIMESTAMP_MODE_RTC
#undef TIMESTAMP_MODE_COUNTER
#if defined(CONFIG_KERNEL_EVENT_LOGGER_CUSTOM_TIMESTAMP)
#if defined(CONFIG_RTC) && !defined(PROFILER_USE_COUNTER)
#define TIMESTAMP_MODE_RTC
#elif defined(CONFIG_COUNTER)
#define TIMESTAMP_MODE_COUNTER
#else
#error KERNEL_EVENT_LOGGER_CUSTOM_TIMESTAMP set but RTC/COUNTER not enabled
#endif
#if defined(TIMESTAMP_MODE_RTC)
#include <rtc.h>
struct device *rtc_dev;
#elif defined(TIMESTAMP_MODE_COUNTER)
#include <counter.h>
struct device *counter_dev;
#endif
#if defined(TIMESTAMP_MODE_RTC)
uint32_t prof_read_timer(void)
{
return rtc_read(rtc_dev);
}
#elif defined(TIMESTAMP_MODE_COUNTER)
uint32_t prof_read_timer(void)
{
return counter_read(counter_dev);
}
#endif
#endif /* CONFIG_KERNEL_EVENT_LOGGER_CUSTOM_TIMESTAMP */
void prof_init(void)
{
#if defined(TIMESTAMP_MODE_RTC)
struct rtc_config config;
rtc_dev = device_get_binding("RTC_0");
config.init_val = 0;
config.alarm_enable = 0;
rtc_enable(rtc_dev);
rtc_set_config(rtc_dev, &config);
sys_k_event_logger_set_timer(prof_read_timer);
#elif defined(TIMESTAMP_MODE_COUNTER)
counter_dev = device_get_binding("AON_COUNTER");
counter_start(counter_dev);
sys_k_event_logger_set_timer(prof_read_timer);
#endif
#ifdef PROFILER_SHELL
#ifndef PROFILER_NO_SHELL_REGISTER
shell_init("shell> ", commands);
#endif
#endif
#if defined(TIMESTAMP_MODE_RTC) || defined(TIMESTAMP_MODE_COUNTER)
prof_pltfm_info.hw_ticks_per_sec = 32768;
#else
prof_pltfm_info.hw_ticks_per_sec = (sys_clock_ticks_per_sec * sys_clock_hw_cycles_per_tick);
#endif
uart_console_dev = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME);
prof_initialized = 1;

View file

@ -17,3 +17,5 @@ CONFIG_TICKLESS_IDLE=y
CONFIG_KERNEL_EVENT_LOGGER_SLEEP=y
CONFIG_UART_QMSI_1_BAUDRATE=2000000
CONFIG_ARC_INIT=n
CONFIG_KERNEL_EVENT_LOGGER_CUSTOM_TIMESTAMP=y
CONFIG_RTC=y

View file

@ -15,3 +15,5 @@ CONFIG_KERNEL_EVENT_LOGGER_INTERRUPT=y
#CONFIG_KERNEL_EVENT_LOGGER_SLEEP=y
CONFIG_UART_QMSI_1_BAUDRATE=2000000
CONFIG_ARC_INIT=n
CONFIG_KERNEL_EVENT_LOGGER_CUSTOM_TIMESTAMP=y
CONFIG_RTC=y