18#ifndef __PERFORMANCE_COUNTER_H__
19#define __PERFORMANCE_COUNTER_H__
25#include "cmsis_compiler.h"
36#define __PERF_COUNTER_VER_MAJOR__ 2
37#define __PERF_COUNTER_VER_MINOR__ 1
38#define __PERF_COUNTER_VER_REVISE__ 0
40#define __PERF_COUNTER_VER_STR__ ""
42#define __PER_COUNTER_VER__ (__PERF_COUNTER_VER_MAJOR__ * 10000ul \
43 +__PERF_COUNTER_VER_MINOR__ * 100ul \
44 +__PERF_COUNTER_VER_REVISE__)
55#undef __IS_COMPILER_IAR__
56#if defined(__IAR_SYSTEMS_ICC__)
57# define __IS_COMPILER_IAR__ 1
61#undef __IS_COMPILER_ARM_COMPILER_5__
62#if ((__ARMCC_VERSION >= 5000000) && (__ARMCC_VERSION < 6000000))
63# define __IS_COMPILER_ARM_COMPILER_5__ 1
69#undef __IS_COMPILER_ARM_COMPILER_6__
70#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
71# define __IS_COMPILER_ARM_COMPILER_6__ 1
73#undef __IS_COMPILER_ARM_COMPILER__
74#if defined(__IS_COMPILER_ARM_COMPILER_5__) && __IS_COMPILER_ARM_COMPILER_5__ \
75|| defined(__IS_COMPILER_ARM_COMPILER_6__) && __IS_COMPILER_ARM_COMPILER_6__
76# define __IS_COMPILER_ARM_COMPILER__ 1
80#undef __IS_COMPILER_LLVM__
81#if defined(__clang__) && !__IS_COMPILER_ARM_COMPILER_6__
82# define __IS_COMPILER_LLVM__ 1
86# undef __IS_COMPILER_GCC__
87# if defined(__GNUC__) && !( defined(__IS_COMPILER_ARM_COMPILER__) \
88 || defined(__IS_COMPILER_LLVM__) \
89 || defined(__IS_COMPILER_IAR__))
90# define __IS_COMPILER_GCC__ 1
96#ifdef __PERF_COUNT_PLATFORM_SPECIFIC_HEADER__
97# include __PERF_COUNT_PLATFORM_SPECIFIC_HEADER__
100#if defined(__clang__)
101# pragma clang diagnostic push
102# pragma clang diagnostic ignored "-Wunknown-warning-option"
103# pragma clang diagnostic ignored "-Wreserved-identifier"
104# pragma clang diagnostic ignored "-Wdeclaration-after-statement"
105# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
106# pragma clang diagnostic ignored "-Wgnu-statement-expression"
107# pragma clang diagnostic ignored "-Wunused-but-set-variable"
108# pragma clang diagnostic ignored "-Wshadow"
109# pragma clang diagnostic ignored "-Wshorten-64-to-32"
110# pragma clang diagnostic ignored "-Wcompound-token-split-by-macro"
111#elif defined(__IS_COMPILER_ARM_COMPILER_5__)
112# pragma diag_suppress 550
113#elif defined(__IS_COMPILER_GCC__)
114# pragma GCC diagnostic push
115# pragma GCC diagnostic ignored "-Wpedantic"
116# pragma GCC diagnostic ignored "-Wunused-variable"
117# pragma GCC diagnostic ignored "-Wunused-but-set-variable"
118# pragma GCC diagnostic ignored "-Wformat="
121#ifndef __PLOOC_VA_NUM_ARGS_IMPL
122# define __PLOOC_VA_NUM_ARGS_IMPL( _0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11, \
123 _12,_13,_14,_15,_16,__N,...) __N
126#ifndef __PLOOC_VA_NUM_ARGS
127#define __PLOOC_VA_NUM_ARGS(...) \
128 __PLOOC_VA_NUM_ARGS_IMPL( 0,##__VA_ARGS__,16,15,14,13,12,11,10,9, \
133# define UNUSED_PARAM(__VAR) (void)(__VAR)
156#undef __MACRO_EXPANDING
157#define __MACRO_EXPANDING(...) __VA_ARGS__
159#define __CONNECT2(__A, __B) __A##__B
160#define __CONNECT3(__A, __B, __C) __A##__B##__C
161#define __CONNECT4(__A, __B, __C, __D) __A##__B##__C##__D
162#define __CONNECT5(__A, __B, __C, __D, __E) __A##__B##__C##__D##__E
163#define __CONNECT6(__A, __B, __C, __D, __E, __F) __A##__B##__C##__D##__E##__F
164#define __CONNECT7(__A, __B, __C, __D, __E, __F, __G) \
165 __A##__B##__C##__D##__E##__F##__G
166#define __CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H) \
167 __A##__B##__C##__D##__E##__F##__G##__H
168#define __CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I) \
169 __A##__B##__C##__D##__E##__F##__G##__H##__I
171#define ALT_CONNECT2(__A, __B) __CONNECT2(__A, __B)
172#define CONNECT2(__A, __B) __CONNECT2(__A, __B)
173#define CONNECT3(__A, __B, __C) __CONNECT3(__A, __B, __C)
174#define CONNECT4(__A, __B, __C, __D) __CONNECT4(__A, __B, __C, __D)
175#define CONNECT5(__A, __B, __C, __D, __E) __CONNECT5(__A, __B, __C, __D, __E)
176#define CONNECT6(__A, __B, __C, __D, __E, __F) \
177 __CONNECT6(__A, __B, __C, __D, __E, __F)
178#define CONNECT7(__A, __B, __C, __D, __E, __F, __G) \
179 __CONNECT7(__A, __B, __C, __D, __E, __F, __G)
180#define CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H) \
181 __CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H)
182#define CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I) \
183 __CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I)
185#define CONNECT(...) \
186 ALT_CONNECT2(CONNECT, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
194#define __using1(__declare) \
195 for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
196 CONNECT3(__using_, __LINE__,_ptr)++ == NULL; \
199#define __using2(__declare, __on_leave_expr) \
200 for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
201 CONNECT3(__using_, __LINE__,_ptr)++ == NULL; \
205#define __using3(__declare, __on_enter_expr, __on_leave_expr) \
206 for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
207 CONNECT3(__using_, __LINE__,_ptr)++ == NULL ? \
208 ((__on_enter_expr),1) : 0; \
212#define __using4(__dcl1, __dcl2, __on_enter_expr, __on_leave_expr) \
213 for (__dcl1, __dcl2, *CONNECT3(__using_, __LINE__,_ptr) = NULL; \
214 CONNECT3(__using_, __LINE__,_ptr)++ == NULL ? \
215 ((__on_enter_expr),1) : 0; \
220 CONNECT2(__using, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
227#define __with2(__type, __addr) \
228 using(__type *_=(__addr))
229#define __with3(__type, __addr, __item) \
230 using(__type *_=(__addr), *__item = _, _=_,_=_ )
233 CONNECT2(__with, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
238# define dimof(__array) (sizeof(__array)/sizeof(__array[0]))
242#define SAFE_NAME(__NAME) CONNECT3(__,__NAME,__LINE__)
248#define foreach2(__type, __array) \
249 using(__type *_ = __array) \
250 for ( uint_fast32_t SAFE_NAME(count) = dimof(__array); \
251 SAFE_NAME(count) > 0; \
252 _++, SAFE_NAME(count)-- \
255#define foreach3(__type, __array, __item) \
256 using(__type *_ = __array, *__item = _, _ = _, _ = _ ) \
257 for ( uint_fast32_t SAFE_NAME(count) = dimof(__array); \
258 SAFE_NAME(count) > 0; \
259 _++, __item = _, SAFE_NAME(count)-- \
262#define foreach(...) \
263 CONNECT2(foreach, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
265#ifndef safe_atom_code
266# define safe_atom_code() \
267 using( uint32_t SAFE_NAME(temp) = \
268 ({ uint32_t SAFE_NAME(temp2)=__get_PRIMASK(); \
270 SAFE_NAME(temp2);}), \
271 __set_PRIMASK(SAFE_NAME(temp)))
276 using( uint32_t SAFE_NAME(temp) = \
277 ({ uint32_t SAFE_NAME(temp2)=__get_PRIMASK(); \
279 SAFE_NAME(temp2);}), \
280 __set_PRIMASK(SAFE_NAME(temp)))
283#ifndef __perf_counter_printf__
284# define __perf_counter_printf__ printf
287#if __PLOOC_VA_NUM_ARGS() != 0
288#warning Please enable GNU extensions, it is required by __cycleof__() and \
289__super_loop_monitor__()
292#if defined(__PERF_COUNTER_CFG_USE_SYSTICK_WRAPPER__)
293# if defined(__IS_COMPILER_ARM_COMPILER_5__) && __IS_COMPILER_ARM_COMPILER_5__
294# pragma import(__ensure_systick_wrapper)
295# elif (defined(__GNUC__) || defined(__clang__)) \
296 && (!defined(__IS_COMPILER_IAR__) || !__IS_COMPILER_IAR__)
297__asm(
".global __ensure_systick_wrapper\n\t");
309#define __cycleof__(__STR, ...) \
310 using(int64_t _ = get_system_ticks(), __cycle_count__ = _, \
312 _ = get_system_ticks() - _ - g_nOffset; \
313 __cycle_count__ = _; \
314 if (__PLOOC_VA_NUM_ARGS(__VA_ARGS__) == 0) { \
315 __perf_counter_printf__("\r\n"); \
316 __perf_counter_printf__("-[Cycle Report]"); \
317 __perf_counter_printf__( \
318 "--------------------------------------------\r\n"); \
319 __perf_counter_printf__( \
320 __STR " total cycle count: %ld [%016lx]\r\n", \
333#define __super_loop_monitor__(__N, ...) \
337 int64_t lTaskUsedCycles; \
338 int64_t lTimeElapsed; \
339 } __cpu_usage__ = {.lStart = get_system_ticks()}) \
340 using(int SAFE_NAME(cnt) = (__N)) \
341 for(start_task_cycle_counter();; ({ \
342 if (!(--SAFE_NAME(cnt))) { \
343 __cpu_usage__.lTimeElapsed \
344 = get_system_ticks() - __cpu_usage__.lStart - g_nOffset; \
345 __cpu_usage__.lTaskUsedCycles = stop_task_cycle_counter(); \
347 if (__PLOOC_VA_NUM_ARGS(__VA_ARGS__) == 0) { \
348 __perf_counter_printf__( \
349 "%s CPU Usage %2.3f%%\r\n", __func__, \
350 (float)((double)__cpu_usage__.lTaskUsedCycles * 100.0 / \
351 (double)__cpu_usage__.lTimeElapsed)); \
355 SAFE_NAME(cnt) = (__N); \
356 __cpu_usage__.lStart = get_system_ticks(); \
357 start_task_cycle_counter(); \
366 uint16_t hwActiveCount;
368 uint16_t bEnabled : 1;
382extern volatile int64_t g_lLastTimeStamp;
383extern volatile int32_t g_nOffset;
397__attribute__((noinline))
431 return lTemp - g_nOffset;
446#ifdef __PERF_CNT_USE_LONG_CLOCK__
468#if !defined(__IS_COMPILER_IAR__)
469__attribute__((nothrow))
471__attribute__((noinline))
472extern int64_t clock(
void);
482#if defined(__PERF_CNT_USE_RTOS__)
556__attribute__((noinline))
573__attribute__((noinline))
577#define start_task_cycle_counter(...) \
578 __start_task_cycle_counter((NULL,##__VA_ARGS__))
580#define stop_task_cycle_counter(...) \
581 __stop_task_cycle_counter((NULL,##__VA_ARGS__))
583#elif !defined(__IMPLEMENT_PERF_COUNTER)
584# define start_task_cycle_counter(...) start_cycle_counter()
585# define stop_task_cycle_counter(...) stop_cycle_counter()
586# define init_task_cycle_counter()
587# define register_task_cycle_agent(...)
588# define unregister_task_cycle_agent(...)
589# define init_task_cycle_info(...) (NULL)
590# define enable_task_cycle_info(...) (false)
591# define disable_task_cycle_info(...) (false)
592# define resume_task_cycle_info(...)
665#ifdef __PERF_COUNTER_COREMARK__
int32_t get_system_us(void)
get the elapsed microsecond since perf_counter is initialised
void user_code_insert_to_systick_handler(void)
a system timer handler inserted to the SysTick_Handler
void update_perf_counter(void)
update perf_counter as SystemCoreClock has been updated.
void delay_ms(int32_t nMs)
delay specified time in millisecond
void start_cycle_counter(void)
try to set a start pointer for the performance counter
int64_t get_system_ticks(void)
get the elapsed cycles since perf_counter is initialised
void init_cycle_counter(bool bIsSysTickOccupied)
initialise cycle counter service
void delay_us(int32_t nUs)
delay specified time in microsecond
int32_t get_system_ms(void)
get the elapsed milliseconds since perf_counter is initialised
int64_t stop_cycle_counter(void)
calculate the elapsed cycle count since the last start point
void coremark_main(void)
entry for coremark
bool disable_task_cycle_info(task_cycle_info_t *ptInfo)
disable a given task_cycle_info_t object
task_cycle_info_agent_t * register_task_cycle_agent(task_cycle_info_t *ptInfo, task_cycle_info_agent_t *ptAgent)
register a global virtual cycle counter agent to the current task
void init_task_cycle_counter(void)
initialize the default virtual cycle counter for the current task
void resume_task_cycle_info(task_cycle_info_t *ptInfo, bool bEnabledStatus)
resume the enabled status of a given task_cycle_info_t object
task_cycle_info_t * get_rtos_task_cycle_info(void)
provide cycle information for target task
bool enable_task_cycle_info(task_cycle_info_t *ptInfo)
enable a given task_cycle_info_t object
task_cycle_info_agent_t * unregister_task_cycle_agent(task_cycle_info_agent_t *ptAgent)
remove a global virtual cycle counter agent from the current task
task_cycle_info_t * init_task_cycle_info(task_cycle_info_t *ptInfo)
intialize a given task_cycle_info_t object and enable it before registering it.