19#undef __PERF_COUNT_PLATFORM_SPECIFIC_HEADER__
24#include "cmsis_compiler.h"
26#define __IMPLEMENT_PERF_COUNTER
27#include "perf_counter.h"
29#if defined(__IS_COMPILER_GCC__)
30# pragma GCC diagnostic ignored "-Wattributes"
34# pragma clang diagnostic ignored "-Wunknown-warning-option"
35# pragma clang diagnostic ignored "-Wreserved-identifier"
36# pragma clang diagnostic ignored "-Wconditional-uninitialized"
37# pragma clang diagnostic ignored "-Wcast-align"
38# pragma clang diagnostic ignored "-Wmissing-prototypes"
43#ifndef PERF_CNT_COMPENSATION_THRESHOLD
44# define PERF_CNT_COMPENSATION_THRESHOLD 16
47#ifndef PERF_CNT_DELAY_US_COMPENSATION
48# define PERF_CNT_DELAY_US_COMPENSATION 90
56 #define __I volatile const
62#define __IM volatile const
67#define SCS_BASE (0xE000E000UL)
68#define SysTick_BASE (SCS_BASE + 0x0010UL)
69#define SCB_BASE (SCS_BASE + 0x0D00UL)
71#define SysTick ((SysTick_Type *) SysTick_BASE )
72#define SCB ((SCB_Type *) SCB_BASE )
75#define SysTick_CTRL_COUNTFLAG_Pos 16U
76#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos)
78#define SysTick_CTRL_CLKSOURCE_Pos 2U
79#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos)
81#define SysTick_CTRL_TICKINT_Pos 1U
82#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos)
84#define SysTick_CTRL_ENABLE_Pos 0U
85#define SysTick_CTRL_ENABLE_Msk (1UL )
88#define SysTick_LOAD_RELOAD_Pos 0U
89#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL )
92#define SysTick_VAL_CURRENT_Pos 0U
93#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL )
96#define SysTick_CALIB_NOREF_Pos 31U
97#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos)
99#define SysTick_CALIB_SKEW_Pos 30U
100#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos)
102#define SysTick_CALIB_TENMS_Pos 0U
103#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL )
107#define SCB_ICSR_PENDSTCLR_Pos 25U
108#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos)
110#define SCB_ICSR_PENDSTSET_Pos 26U
111#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos)
114#define MAGIC_WORD_AGENT_LIST_VALID 0x8492A53C
115#define MAGIC_WORD_CANARY 0xDEADBEEF
139 __IOM uint32_t AIRCR;
142 __IOM uint8_t SHP[12U];
143 __IOM uint32_t SHCSR;
147 __IOM uint32_t MMFAR;
150 __IM uint32_t PFR[2U];
153 __IM uint32_t MMFR[4U];
154 __IM uint32_t ISAR[5U];
155 uint32_t RESERVED0[5U];
156 __IOM uint32_t CPACR;
159struct __task_cycle_info_t {
161 int64_t lLastTimeStamp;
168extern uint32_t SystemCoreClock;
171volatile int64_t g_lLastTimeStamp = 0;
172volatile int32_t g_nOffset = 0;
173volatile static int32_t s_nUSUnit = 1;
174volatile static int32_t s_nMSUnit = 1;
175volatile static int32_t s_nMSResidule = 0;
176volatile static int32_t s_nUSResidule = 0;
177volatile static int32_t s_nSystemMS = 0;
178volatile static int32_t s_nSystemUS = 0;
180volatile static int64_t s_lSystemClockCounts = 0;
187__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
189 if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
197 SysTick->LOAD = (uint32_t)(ticks - 1UL);
200 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
201 SysTick_CTRL_TICKINT_Msk |
202 SysTick_CTRL_ENABLE_Msk;
210 uint32_t wLoad = SysTick->LOAD + 1;
211 s_lSystemClockCounts += wLoad;
215 s_nMSResidule += wLoad;
216 int32_t nMS = s_nMSResidule / s_nMSUnit;
217 s_nMSResidule -= nMS * s_nMSUnit;
223 s_nUSResidule += wLoad;
224 int32_t nUS = s_nUSResidule / s_nUSUnit;
225 s_nUSResidule -= nUS * s_nUSUnit;
232void __perf_os_patch_init(
void)
239 s_nUSUnit = SystemCoreClock / 1000000ul;
240 s_nMSUnit = SystemCoreClock / 1000ul;
252 if (!bIsSysTickOccupied) {
253 SysTick_Config(0x01000000);
255 SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk;
259 s_lSystemClockCounts = 0;
263 __perf_os_patch_init();
270__STATIC_INLINE int32_t check_systick(
void)
272 int32_t nTemp = (int32_t)SysTick->LOAD - (int32_t)SysTick->VAL;
294 if (SCB->ICSR & SCB_ICSR_PENDSTSET_Msk){
295 if (((int32_t)SysTick->LOAD - nTemp) >= PERF_CNT_COMPENSATION_THRESHOLD) {
296 nTemp += SysTick->LOAD + 1;
303__attribute__((constructor))
304void __perf_counter_init(
void)
312 int64_t lUs = (int64_t)nUs * (int64_t)s_nUSUnit;
313 int32_t iCompensate = g_nOffset > PERF_CNT_DELAY_US_COMPENSATION
315 : PERF_CNT_DELAY_US_COMPENSATION;
317 if (lUs <= iCompensate) {
330 int64_t lUs = (int64_t)nMs * (int64_t)s_nMSUnit;
331 int32_t iCompensate = g_nOffset > PERF_CNT_DELAY_US_COMPENSATION
333 : PERF_CNT_DELAY_US_COMPENSATION;
335 if (lUs <= iCompensate) {
345__attribute__((noinline))
351 lTemp = check_systick() + s_lSystemClockCounts;
378#if !defined(__IS_COMPILER_IAR__)
379__attribute__((nothrow))
381__attribute__((noinline))
392 nTemp = s_nSystemMS + (check_systick() + s_nMSResidule) / s_nMSUnit;
403 nTemp = s_nSystemUS + (check_systick() + s_nUSResidule) / s_nUSUnit;
412uint32_t EventRecorderTimerSetup (
void)
420uint32_t EventRecorderTimerGetFreq (
void)
422 return SystemCoreClock;
427uint32_t EventRecorderTimerGetCount (
void)
442 struct __task_cycle_info_t * ptRootAgent =
444 if (NULL == ptRootAgent) {
448 memset(ptRootAgent, 0,
sizeof(
struct __task_cycle_info_t));
450 ptRootAgent->tList.ptInfo = &(ptRootAgent->tInfo);
452 ptRootAgent->wMagicWord = MAGIC_WORD_CANARY;
458 if (NULL == ptInfo) {
464 ptInfo->bEnabled =
true;
472 if (NULL == ptInfo) {
477 bOrig = ptInfo->bEnabled;
478 ptInfo->bEnabled =
true;
485 if (NULL == ptInfo) {
490 bOrig = ptInfo->bEnabled;
491 ptInfo->bEnabled =
false;
498 if (NULL == ptInfo) {
502 ptInfo->bEnabled = bEnabledStatus;
511 if (NULL == ptAgent || NULL == ptInfo) {
515 struct __task_cycle_info_t * ptRootAgent =
517 if (NULL == ptRootAgent) {
521 ptRootAgent->wMagicWord = MAGIC_WORD_AGENT_LIST_VALID;
523 ptAgent->ptInfo = ptInfo;
528 ptAgent->ptNext = ptRootAgent->tList.ptNext;
529 ptRootAgent->tList.ptNext = ptAgent;
532 ptAgent->ptPrev = &(ptRootAgent->tList);
533 if (NULL != ptAgent->ptNext) {
534 ptAgent->ptNext->ptPrev = ptAgent;
549 if (NULL == ptAgent) {
554 if (NULL == ptPrev) {
557 if (ptPrev->ptNext != ptAgent) {
563 ptPrev->ptNext = ptAgent->ptNext;
565 if (NULL != ptAgent->ptNext) {
567 ptAgent->ptNext->ptPrev = ptPrev;
570 ptAgent->ptNext = NULL;
571 ptAgent->ptPrev = NULL;
580void __on_context_switch_in(uint32_t *pwStack)
582 struct __task_cycle_info_t *ptRootAgent = (
struct __task_cycle_info_t *)pwStack;
585 ptRootAgent->lLastTimeStamp = lTimeStamp;
586 ptRootAgent->tInfo.hwActiveCount++;
588 if (MAGIC_WORD_AGENT_LIST_VALID == ptRootAgent->wMagicWord) {
591 while(NULL != ptAgent) {
592 if (NULL != ptAgent->ptInfo) {
593 if (ptAgent->ptInfo->bEnabled) {
594 ptAgent->ptInfo->hwActiveCount++;
597 ptAgent = ptAgent->ptNext;
602void __on_context_switch_out(uint32_t *pwStack)
604 struct __task_cycle_info_t *ptRootAgent = (
struct __task_cycle_info_t *)pwStack;
605 int64_t lCycleUsed =
get_system_ticks() - ptRootAgent->lLastTimeStamp - g_nOffset;
607 ptRootAgent->tInfo.nUsedRecent = lCycleUsed;
608 ptRootAgent->tInfo.lUsedTotal += lCycleUsed;
610 if (MAGIC_WORD_AGENT_LIST_VALID == ptRootAgent->wMagicWord) {
613 while(NULL != ptAgent) {
614 if (NULL != ptAgent->ptInfo) {
615 if (ptAgent->ptInfo->bEnabled) {
616 ptAgent->ptInfo->nUsedRecent = lCycleUsed;
617 ptAgent->ptInfo->lUsedTotal += lCycleUsed;
620 ptAgent = ptAgent->ptNext;
625__attribute__((noinline))
628 struct __task_cycle_info_t * ptRootAgent =
630 if (NULL == ptRootAgent) {
636 ptRootAgent->tInfo.lUsedTotal = 0;
638 if (NULL != ptInfo) {
639 ptInfo->lUsedTotal = 0;
640 ptInfo->bEnabled =
true;
645__attribute__((noinline))
648 struct __task_cycle_info_t * ptRootAgent =
650 if (NULL == ptRootAgent) {
657 int64_t lCycleUsed =
get_system_ticks() - ptRootAgent->lLastTimeStamp - g_nOffset;
658 ptRootAgent->tInfo.lUsedTotal += lCycleUsed;
660 if (NULL != ptInfo) {
661 if (ptInfo->bEnabled) {
662 ptInfo->nUsedRecent = lCycleUsed;
663 ptInfo->lUsedTotal += lCycleUsed;
664 ptInfo->bEnabled =
false;
667 lCycles = ptInfo->lUsedTotal;
669 lCycles = ptRootAgent->tInfo.lUsedTotal;
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
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
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
__WEAK 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.