This commit is contained in:
Gabriel Wang 2024-12-08 18:52:01 +00:00
parent 8895f2ba5e
commit 0ff3224151
7 changed files with 255 additions and 60 deletions

View File

@ -130,7 +130,7 @@
<SetRegEntry>
<Number>0</Number>
<Key>DbgFM</Key>
<Name>-I -S"System Generator:cpu_core" -L"armcortexm0ct" -O4102 -C0 -MC".\VHT\VHT_MPS2_Cortex-M0.exe" -MF -PF -MA</Name>
<Name>-I -S"System Generator:FVP_MPS2_Cortex_M0" -L"armcortexm0ct" -O4102 -C0 -MC".\avh-fvp\bin\models\FVP_MPS2_Cortex-M0.exe" -MF -PF -MA</Name>
</SetRegEntry>
<SetRegEntry>
<Number>0</Number>
@ -204,7 +204,7 @@
<DebugFlag>
<trace>0</trace>
<periodic>1</periodic>
<aLwin>1</aLwin>
<aLwin>0</aLwin>
<aCover>0</aCover>
<aSer1>0</aSer1>
<aSer2>0</aSer2>
@ -221,7 +221,7 @@
<aLa>0</aLa>
<aPa1>0</aPa1>
<AscS4>0</AscS4>
<aSer4>0</aSer4>
<aSer4>1</aSer4>
<StkLoc>0</StkLoc>
<TrcWin>0</TrcWin>
<newCpu>0</newCpu>
@ -817,7 +817,7 @@
<Group>
<GroupName>::Device</GroupName>
<tvExp>1</tvExp>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>1</RteFlg>

View File

@ -10,7 +10,7 @@
<TargetName>example_arm_compiler_6</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6220000::V6.22::ARMCLANG</pCCUsed>
<pCCUsed>6230000::V6.23::.\ArmCompilerforEmbedded6.24</pCCUsed>
<uAC6>1</uAC6>
<TargetOption>
<TargetCommonOption>
@ -134,11 +134,11 @@
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
<Capability>0</Capability>
<DriverSelection>-1</DriverSelection>
<DriverSelection>4096</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3></Flash3>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
@ -449,7 +449,7 @@
<TargetName>library</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pCCUsed>6210000::V6.21::ARMCLANG</pCCUsed>
<pCCUsed>6230000::V6.23::.\ArmCompilerforEmbedded6.24</pCCUsed>
<uAC6>1</uAC6>
<TargetOption>
<TargetCommonOption>

View File

@ -75,7 +75,7 @@
<OPTFL>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<IsCurrentTarget>1</IsCurrentTarget>
<IsCurrentTarget>0</IsCurrentTarget>
</OPTFL>
<CpuCode>7</CpuCode>
<DebugOpt>
@ -280,7 +280,7 @@
<OPTFL>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<IsCurrentTarget>0</IsCurrentTarget>
<IsCurrentTarget>1</IsCurrentTarget>
</OPTFL>
<CpuCode>7</CpuCode>
<DebugOpt>

View File

@ -19,6 +19,7 @@
#include <stdio.h>
#include <cmsis_compiler.h>
#include "perf_counter.h"
#include <stdlib.h>
#ifndef __PERF_CNT_USE_LONG_CLOCK__
@ -126,6 +127,47 @@ uint32_t calculate_stack_usage_bottomup(void)
/*----------------------------------------------------------------------------
Main function
*----------------------------------------------------------------------------*/
typedef struct {
uint8_t chPT;
void *ptResource;
} pt_led_flash_cb_t;
#undef this
#define this (*ptThis)
fsm_rt_t pt_example_led_flash(pt_led_flash_cb_t *ptThis)
{
PERFC_PT_BEGIN(this.chPT)
do {
PERFC_PT_WAIT_RESOURCE_UNTIL(
(this.ptResource != NULL), /* quit condition */
this.ptResource = malloc(100); /* try to allocate memory */
)
printf("LED ON [%lld]\r\n", get_system_ms());
PERFC_PT_DELAY_MS(500);
printf("LED OFF [%lld]\r\n", get_system_ms());
PERFC_PT_DELAY_MS(500);
free(this.ptResource);
} while(1);
PERFC_PT_END()
return fsm_rt_cpl;
}
static pt_led_flash_cb_t s_tExamplePT = {0};
int main (void)
{
int32_t iCycleResult = 0;
@ -205,10 +247,9 @@ int main (void)
}) {
delay_us(50000);
}
delay_us(20000);
delay_us(20000);
pt_example_led_flash(&s_tExamplePT);
}
}

View File

@ -64,9 +64,10 @@ struct __task_cycle_info_t {
/*============================ GLOBAL VARIABLES ==============================*/
/*============================ LOCAL VARIABLES ===============================*/
volatile int64_t g_lLastTimeStamp = 0;
volatile static int64_t s_lOldTimestamp;
volatile int32_t g_nOffset = 0;
volatile static int64_t s_lOldTimestampUS;
volatile static int64_t s_lOldTimestampMS;
volatile static uint32_t s_wUSUnit = 1;
volatile static uint32_t s_wMSUnit = 1;
volatile static uint32_t s_wMSResidule = 0;
@ -76,6 +77,9 @@ volatile static int64_t s_lSystemUS = 0;
volatile static int64_t s_lSystemClockCounts = 0;
volatile int32_t g_nOffset = 0;
volatile int64_t g_lLastTimeStamp = 0;
/*============================ PROTOTYPES ====================================*/
/* low level interface for porting */
@ -112,22 +116,23 @@ void perfc_port_insert_to_system_timer_insert_ovf_handler(void)
// update system ms counter
do {
int64_t lTemp = s_wMSResidule + lLoad;
int64_t lMS = lTemp / s_wMSUnit;
s_lSystemMS += lMS;
s_wMSResidule = (uint32_t)((int64_t)lTemp - (int64_t)lMS * s_wMSUnit);
} while(0);
}
__IRQ_SAFE {
// update system us counter
do {
int64_t lTemp = s_wUSResidule + lLoad;
int64_t lUS = lTemp / s_wUSUnit;
s_lSystemUS += lUS;
s_wUSResidule = (uint32_t)((int64_t)lTemp - (int64_t)lUS * s_wUSUnit);
} while(0);
}
}
@ -169,6 +174,8 @@ bool init_cycle_counter(bool bIsSysTickOccupied)
s_lSystemMS = 0; // reset system millisecond counter
s_lSystemUS = 0; // reset system microsecond counter
s_lOldTimestamp = 0;
s_lOldTimestampUS = 0;
s_lOldTimestampMS = 0;
__perf_os_patch_init();
@ -322,7 +329,15 @@ int64_t get_system_ms(void)
int64_t lTemp = 0;
__IRQ_SAFE {
lTemp = s_lSystemMS + ((check_systick() + (int64_t)s_wMSResidule) / s_wMSUnit);
lTemp = s_lSystemMS
+ ( (check_systick()
+ (int64_t)s_wMSResidule) / s_wMSUnit);
if (lTemp < s_lOldTimestampMS) {
lTemp = s_lOldTimestampMS;
} else {
s_lOldTimestampMS = lTemp;
}
}
return lTemp;
@ -333,7 +348,16 @@ int64_t get_system_us(void)
int64_t lTemp = 0;
__IRQ_SAFE {
lTemp = s_lSystemUS + ((check_systick() + (int64_t)s_wUSResidule) / s_wUSUnit);
lTemp = s_lSystemUS
+ ( (check_systick()
+ (int64_t)s_wUSResidule) / s_wUSUnit);
if (lTemp < s_lOldTimestampUS) {
lTemp = s_lOldTimestampUS;
} else {
s_lOldTimestampUS = lTemp;
}
}
return lTemp;
@ -370,7 +394,6 @@ bool __perfc_is_time_out(int64_t lPeriod, int64_t *plTimestamp, bool bAutoReload
int64_t lTimestamp = get_system_ticks();
if (0 == *plTimestamp) {
*plTimestamp = lPeriod;
*plTimestamp += lTimestamp;
@ -411,8 +434,6 @@ uint32_t EventRecorderTimerGetCount (void)
return get_system_ticks();
}
__WEAK
task_cycle_info_t * get_rtos_task_cycle_info(void)
{

View File

@ -39,8 +39,8 @@ extern "C" {
* @{
*/
#define __PERF_COUNTER_VER_MAJOR__ 2
#define __PERF_COUNTER_VER_MINOR__ 3
#define __PERF_COUNTER_VER_REVISE__ 3
#define __PERF_COUNTER_VER_MINOR__ 4
#define __PERF_COUNTER_VER_REVISE__ 0
#define __PERF_COUNTER_VER_STR__ ""
@ -275,7 +275,8 @@ extern "C" {
#endif
#define SAFE_NAME(__NAME) CONNECT3(__,__NAME,__LINE__)
#define SAFE_NAME(__NAME) CONNECT3(__,__NAME,__LINE__)
#define PERFC_SAFE_NAME(__name) CONNECT3(__,__name,__LINE__)
#undef foreach2
#undef foreach3
@ -283,23 +284,23 @@ extern "C" {
#define foreach1(__array) \
using(__typeof__(__array[0]) *_ = __array) \
for ( uint_fast32_t SAFE_NAME(count) = dimof(__array); \
SAFE_NAME(count) > 0; \
_++, SAFE_NAME(count)-- \
for ( uint_fast32_t PERFC_SAFE_NAME(count) = dimof(__array); \
PERFC_SAFE_NAME(count) > 0; \
_++, PERFC_SAFE_NAME(count)-- \
)
#define foreach2(__type, __array) \
using(__type *_ = __array) \
for ( uint_fast32_t SAFE_NAME(count) = dimof(__array); \
SAFE_NAME(count) > 0; \
_++, SAFE_NAME(count)-- \
for ( uint_fast32_t PERFC_SAFE_NAME(count) = dimof(__array); \
PERFC_SAFE_NAME(count) > 0; \
_++, PERFC_SAFE_NAME(count)-- \
)
#define foreach3(__type, __array, __item) \
using(__type *_ = __array, *__item = _, _ = _, _ = _ ) \
for ( uint_fast32_t SAFE_NAME(count) = dimof(__array); \
SAFE_NAME(count) > 0; \
_++, __item = _, SAFE_NAME(count)-- \
for ( uint_fast32_t PERFC_SAFE_NAME(count) = dimof(__array); \
PERFC_SAFE_NAME(count) > 0; \
_++, __item = _, PERFC_SAFE_NAME(count)-- \
)
#define foreach(...) \
@ -415,29 +416,30 @@ __asm(".global __ensure_systick_wrapper\n\t");
\endcode
*/
#define __cpu_usage__(__CNT, ...) \
static int64_t SAFE_NAME(s_lTimestamp) = 0, SAFE_NAME(s_lTotal) = 0; \
static uint32_t SAFE_NAME(s_wLoopCounter) = (__CNT); \
static int64_t PERFC_SAFE_NAME(s_lTimestamp) = 0, \
PERFC_SAFE_NAME(s_lTotal) = 0; \
static uint32_t PERFC_SAFE_NAME(s_wLoopCounter) = (__CNT); \
using(float __usage__ = 0, ({ \
if (0 == SAFE_NAME(s_wLoopCounter)) { \
__usage__ = (float)((double)SAFE_NAME(s_lTotal) \
if (0 == PERFC_SAFE_NAME(s_wLoopCounter)) { \
__usage__ = (float)((double)PERFC_SAFE_NAME(s_lTotal) \
/ (double)( get_system_ticks() \
- SAFE_NAME(s_lTimestamp))); \
- PERFC_SAFE_NAME(s_lTimestamp))); \
__usage__ *= 100.0f; \
SAFE_NAME(s_lTimestamp) = 0; \
SAFE_NAME(s_lTotal) = 0; \
PERFC_SAFE_NAME(s_lTimestamp) = 0; \
PERFC_SAFE_NAME(s_lTotal) = 0; \
if (__PLOOC_VA_NUM_ARGS(__VA_ARGS__) == 0) { \
__perf_counter_printf__("CPU Usage %3.2f%%\r\n", (double)__usage__);\
} else { \
__VA_ARGS__ \
} \
} \
if (0 == SAFE_NAME(s_lTimestamp)) { \
SAFE_NAME(s_lTimestamp) = get_system_ticks(); \
SAFE_NAME(s_wLoopCounter) = (__CNT); \
if (0 == PERFC_SAFE_NAME(s_lTimestamp)) { \
PERFC_SAFE_NAME(s_lTimestamp) = get_system_ticks(); \
PERFC_SAFE_NAME(s_wLoopCounter) = (__CNT); \
} \
start_task_cycle_counter();}), \
({SAFE_NAME(s_lTotal) += stop_task_cycle_counter(); \
SAFE_NAME(s_wLoopCounter)--;}))
({PERFC_SAFE_NAME(s_lTotal) += stop_task_cycle_counter(); \
PERFC_SAFE_NAME(s_wLoopCounter)--;}))
#define __cpu_time__ __cpu_usage__
@ -462,7 +464,8 @@ __asm(".global __ensure_systick_wrapper\n\t");
* \return bool whether it is timeout
*/
#define perfc_is_time_out_ms3(__ms, __timestamp_ptr, __auto_reload) \
({ static int64_t SAFE_NAME(s_lTimestamp); (void)SAFE_NAME(s_lTimestamp); \
({ static int64_t PERFC_SAFE_NAME(s_lTimestamp); \
(void)PERFC_SAFE_NAME(s_lTimestamp); \
__perfc_is_time_out(perfc_convert_ms_to_ticks(__ms), \
(__timestamp_ptr), (__auto_reload));})
@ -487,7 +490,7 @@ __asm(".global __ensure_systick_wrapper\n\t");
* \return bool whether it is timeout
*/
#define perfc_is_time_out_ms1(__ms) \
perfc_is_time_out_ms3((__ms), &SAFE_NAME(s_lTimestamp), true)
perfc_is_time_out_ms3((__ms), &PERFC_SAFE_NAME(s_lTimestamp), true)
/*!
* \brief set an alarm with given period in ms and check the status
@ -512,7 +515,8 @@ __asm(".global __ensure_systick_wrapper\n\t");
* \return bool whether it is timeout
*/
#define perfc_is_time_out_us3(__us, __timestamp_ptr, __auto_reload) \
({ static int64_t SAFE_NAME(s_lTimestamp); (void)SAFE_NAME(s_lTimestamp); \
({ static int64_t PERFC_SAFE_NAME(s_lTimestamp); \
(void)PERFC_SAFE_NAME(s_lTimestamp); \
__perfc_is_time_out(perfc_convert_us_to_ticks(__us), \
(__timestamp_ptr), (__auto_reload));})
@ -568,9 +572,9 @@ __asm(".global __ensure_systick_wrapper\n\t");
int64_t lTaskUsedCycles; \
int64_t lTimeElapsed; \
} __cpu_usage__ = {.lStart = get_system_ticks()}) \
using(int SAFE_NAME(cnt) = (__N)) \
using(int PERFC_SAFE_NAME(cnt) = (__N)) \
for(start_task_cycle_counter();; ({ \
if (!(--SAFE_NAME(cnt))) { \
if (!(--PERFC_SAFE_NAME(cnt))) { \
__cpu_usage__.lTimeElapsed \
= get_system_ticks() - __cpu_usage__.lStart - g_nOffset; \
__cpu_usage__.lTaskUsedCycles = stop_task_cycle_counter(); \
@ -583,13 +587,142 @@ __asm(".global __ensure_systick_wrapper\n\t");
} else { \
__VA_ARGS__; \
} \
SAFE_NAME(cnt) = (__N); \
PERFC_SAFE_NAME(cnt) = (__N); \
__cpu_usage__.lStart = get_system_ticks(); \
start_task_cycle_counter(); \
}; \
}))
/*----------------------------------------------------------------------------*
* PT Operations *
*----------------------------------------------------------------------------*/
/*
Protothreads open source BSD-style license
The protothreads library is released under an open source license that allows
both commercial and non-commercial use without restrictions. The only
requirement is that credits is given in the source code and in the documentation
for your product.
The full license text follows.
Copyright (c) 2004-2005, Swedish Institute of Computer Science.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the Institute nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS `AS IS' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Author: Adam Dunkels
*/
#define PERFC_PT_BEGIN(__state) \
enum { \
count_offset = __COUNTER__ + 1, \
}; \
uint8_t *ptPTState = &(__state); \
switch (__state) { \
case __COUNTER__ - count_offset:
#define PERFC_PT_ENTRY(...) \
(*ptPTState) = (__COUNTER__ - count_offset + 1) >> 1; \
__VA_ARGS__ \
case (__COUNTER__ - count_offset) >> 1: (void)(*ptPTState);
#define PERFC_PT_YIELD(...) \
PERFC_PT_ENTRY(return __VA_ARGS__;)
#define PERFC_PT_END() \
(*ptPTState) = 0; \
break;}
#define PERFC_PT_GOTO_PREV_ENTRY(...) return __VA_ARGS__;
#define PERFC_PT_WAIT_UNTIL(__CONDITION, ...) \
PERFC_PT_ENTRY() \
__VA_ARGS__; \
if (!(__CONDITION)) { \
PERFC_PT_GOTO_PREV_ENTRY(fsm_rt_on_going); \
}
#define PERFC_PT_WAIT_OBJ_UNTIL(__CONDITION, ...) \
perfc_pt__ENTRY() \
__VA_ARGS__; \
if (!(__CONDITION)) { \
PERFC_PT_GOTO_PREV_ENTRY(fsm_rt_wait_for_obj); \
}
#define PERFC_PT_WAIT_RESOURCE_UNTIL(__CONDITION, ...) \
PERFC_PT_ENTRY() \
__VA_ARGS__; \
if (!(__CONDITION)) { \
PERFC_PT_GOTO_PREV_ENTRY(fsm_rt_wait_for_res); \
}
#define PERFC_PT_DELAY_MS(__ms, ...) \
PERFC_PT_ENTRY( \
static int64_t PERFC_SAFE_NAME(s_lTimestamp); \
UNUSED_PARAM(PERFC_SAFE_NAME(s_lTimestamp)); \
int64_t *PERFC_SAFE_NAME(plTimestamp) \
= (&PERFC_SAFE_NAME(s_lTimestamp), ##__VA_ARGS__); \
*PERFC_SAFE_NAME(plTimestamp) = get_system_ms(); \
) \
do { \
PERFC_SAFE_NAME(plTimestamp) \
= (&PERFC_SAFE_NAME(s_lTimestamp), ##__VA_ARGS__); \
int64_t PERFC_SAFE_NAME(lElapsedMs) = \
get_system_ms() - *PERFC_SAFE_NAME(plTimestamp); \
if (PERFC_SAFE_NAME(lElapsedMs) < (__ms)) { \
PERFC_PT_GOTO_PREV_ENTRY(fsm_rt_on_going); \
} \
} while(0)
#define PERFC_PT_REPORT_STATUS(...) \
PERFC_PT_ENTRY( \
return __VA_ARGS__; \
)
#define PERFC_PT_RETURN(...) \
(*ptPTState) = 0; \
return __VA_ARGS__;
/*============================ TYPES =========================================*/
#ifndef __FSM_RT_TYPE__
# define __FSM_RT_TYPE__
//! \name finit state machine state
//! @{
typedef enum {
fsm_rt_err = -1, //!< fsm error, error code can be get from other interface
fsm_rt_cpl = 0, //!< fsm complete
fsm_rt_on_going = 1, //!< fsm on-going
fsm_rt_wait_for_obj = 2, //!< fsm wait for object
fsm_rt_asyn = 3, //!< fsm asynchronose complete, you can check it later.
fsm_rt_wait_for_res = 4, //!< fsm wait for resource
} fsm_rt_t;
//! @}
#endif
typedef struct {
int64_t lStart;
int64_t lUsedTotal;

View File

@ -15,15 +15,15 @@
;* *
;****************************************************************************/
.syntax unified
.arch armv6-m
.syntax unified
.arch armv6-m
.text
.thumb
.thumb_func
.align 2
.globl __wrap_SysTick_Handler
.type __wrap_SysTick_Handler, %function
.align 2
.globl __wrap_SysTick_Handler
.type __wrap_SysTick_Handler, %function
__wrap_SysTick_Handler:
push {r4, r5}
@ -41,4 +41,4 @@ __wrap_SysTick_Handler:
.type __ensure_systick_wrapper, %function
__ensure_systick_wrapper:
bx lr
bx lr