diff --git a/arch/arc/defconfig b/arch/arc/defconfig index 1eb306e8534..5147264f5db 100644 --- a/arch/arc/defconfig +++ b/arch/arc/defconfig @@ -18,6 +18,7 @@ CONFIG_XIP=y # CONFIG_PROFILER_BUFFER_SIZE is not set # CONFIG_PROFILER_CONTEXT_SWITCH is not set # CONFIG_PROFILER_INTERRUPT is not set +# CONFIG_PROFILER_SLEEP is not set # # Nanokernel Options diff --git a/arch/arm/core/cpu_idle.S b/arch/arm/core/cpu_idle.S index fc51f1f39ad..ff24c06133c 100644 --- a/arch/arm/core/cpu_idle.S +++ b/arch/arm/core/cpu_idle.S @@ -134,6 +134,12 @@ SECTION_FUNC(TEXT, _NanoIdleValClear) */ SECTION_FUNC(TEXT, nano_cpu_idle) +#ifdef CONFIG_PROFILER_SLEEP + push {lr} + bl _sys_profiler_enter_sleep + pop {lr} +#endif + /* clear BASEPRI so wfi is awakened by incoming interrupts */ eors.n r0, r0 msr BASEPRI, r0 @@ -169,6 +175,11 @@ SECTION_FUNC(TEXT, nano_cpu_idle) */ SECTION_FUNC(TEXT, nano_cpu_atomic_idle) +#ifdef CONFIG_PROFILER_SLEEP + push {lr} + bl _sys_profiler_enter_sleep + pop {lr} +#endif /* * r0: interrupt mask from caller diff --git a/arch/arm/defconfig b/arch/arm/defconfig index 094cd391619..8317f8b3058 100644 --- a/arch/arm/defconfig +++ b/arch/arm/defconfig @@ -19,6 +19,7 @@ CONFIG_XIP=y # CONFIG_PROFILER_BUFFER_SIZE is not set # CONFIG_PROFILER_CONTEXT_SWITCH is not set # CONFIG_PROFILER_INTERRUPT is not set +# CONFIG_PROFILER_SLEEP is not set # # Nanokernel Options diff --git a/arch/x86/core/cpuhalt.S b/arch/x86/core/cpuhalt.S index a4ff9a5d224..f42377f1bd5 100644 --- a/arch/x86/core/cpuhalt.S +++ b/arch/x86/core/cpuhalt.S @@ -84,6 +84,9 @@ SECTION_FUNC(TEXT, nano_cpu_idle) #ifdef CONFIG_INT_LATENCY_BENCHMARK call _int_latency_stop #endif +#ifdef CONFIG_PROFILER_SLEEP + call _sys_profiler_enter_sleep +#endif #if defined(CONFIG_BOOT_TIME_MEASUREMENT) rdtsc /* record idle timestamp */ mov %eax, __idle_tsc /* ... low 32 bits */ @@ -123,6 +126,9 @@ SECTION_FUNC(TEXT, nano_cpu_idle) SECTION_FUNC(TEXT, nano_cpu_atomic_idle) #ifdef CONFIG_INT_LATENCY_BENCHMARK call _int_latency_stop +#endif +#ifdef CONFIG_PROFILER_SLEEP + call _sys_profiler_enter_sleep #endif sti /* make sure interrupts are enabled */ diff --git a/arch/x86/defconfig b/arch/x86/defconfig index 6d8d8f375ee..3f8471011be 100644 --- a/arch/x86/defconfig +++ b/arch/x86/defconfig @@ -21,6 +21,7 @@ CONFIG_ENHANCED_SECURITY=y # CONFIG_PROFILER_BUFFER_SIZE is not set # CONFIG_PROFILER_CONTEXT_SWITCH is not set # CONFIG_PROFILER_INTERRUPT is not set +# CONFIG_PROFILER_SLEEP is not set # # Security Options diff --git a/include/misc/profiler.h b/include/misc/profiler.h index d1a4b85fd6a..dac14c7a803 100644 --- a/include/misc/profiler.h +++ b/include/misc/profiler.h @@ -49,6 +49,10 @@ #define PROFILER_INTERRUPT_EVENT_ID 0x0002 #endif +#ifdef CONFIG_PROFILER_SLEEP +#define PROFILER_SLEEP_EVENT_ID 0x0003 +#endif + #ifndef _ASMLANGUAGE /** * Global variable of the ring buffer that allows user to implement diff --git a/kernel/Kconfig b/kernel/Kconfig index 7ce0caff263..494e8760597 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -150,6 +150,17 @@ config PROFILER_INTERRUPT Enable interrupt event messages. These messages provide the following information: The time when interrupts occur. +config PROFILER_SLEEP + bool + prompt "Sleep profiler point" + default n + depends on KERNEL_PROFILER && ADVANCED_POWER_MANAGEMENT + help + Enable low power condition event messages. These messages provide the + following information: + - When the CPU went to sleep mode. + - When the CPU woke up. + - The ID of the interrupt that woke the CPU up. endmenu menu "Security Options" diff --git a/kernel/microkernel/k_idle.c b/kernel/microkernel/k_idle.c index 2a5faf76a2a..aa66ca4ad1f 100644 --- a/kernel/microkernel/k_idle.c +++ b/kernel/microkernel/k_idle.c @@ -370,6 +370,10 @@ void _sys_power_save_idle_exit(int32_t ticks) #else ARG_UNUSED(ticks); #endif /* CONFIG_TICKLESS_IDLE */ +#ifdef CONFIG_PROFILER_SLEEP + extern void _sys_profiler_exit_sleep(void); + _sys_profiler_exit_sleep(); +#endif } /** diff --git a/kernel/nanokernel/profiler.c b/kernel/nanokernel/profiler.c index 0ebe45ef7fc..aca41259a71 100644 --- a/kernel/nanokernel/profiler.c +++ b/kernel/nanokernel/profiler.c @@ -46,6 +46,11 @@ uint32_t _sys_profiler_buffer[CONFIG_PROFILER_BUFFER_SIZE]; void *_collector_fiber=NULL; #endif +#ifdef CONFIG_PROFILER_SLEEP +uint32_t _sys_profiler_sleep_start_time; +#endif + + /** * @brief Initialize the profiler system. * @@ -134,3 +139,23 @@ void _sys_profiler_interrupt() sys_profiler_put(PROFILER_INTERRUPT_EVENT_ID, data, ARRAY_SIZE(data)); } #endif /* CONFIG_PROFILER_INTERRUPT */ + + +#ifdef CONFIG_PROFILER_SLEEP +void _sys_profiler_enter_sleep(void) +{ + _sys_profiler_sleep_start_time = nano_cycle_get_32(); +} + +void _sys_profiler_exit_sleep(void) +{ + uint32_t data[3]; + + data[0] = nano_tick_get_32(); + data[1] = (nano_cycle_get_32() - _sys_profiler_sleep_start_time) / sys_clock_hw_cycles_per_tick; + /* register the cause of exiting sleep mode */ + data[2] = _sys_current_irq_key_get(); + + sys_profiler_put(PROFILER_SLEEP_EVENT_ID, data, ARRAY_SIZE(data)); +} +#endif /* CONFIG_PROFILER_SLEEP */