diff --git a/example/example.uvoptx b/example/example.uvoptx index 15b1e38..6b030b1 100644 --- a/example/example.uvoptx +++ b/example/example.uvoptx @@ -130,7 +130,7 @@ 0 DbgFM - -I -S"System Generator:cpu_core" -L"armcortexm0ct" -O4102 -C0 -MC".\VHT\VHT_MPS2_Cortex-M0.exe" -MF -PF -MA + -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 0 @@ -204,7 +204,7 @@ 0 1 - 1 + 0 0 0 0 @@ -221,7 +221,7 @@ 0 0 0 - 0 + 1 0 0 0 @@ -817,7 +817,7 @@ ::Device - 1 + 0 0 0 1 diff --git a/example/example.uvprojx b/example/example.uvprojx index 85de1cf..704fbd8 100644 --- a/example/example.uvprojx +++ b/example/example.uvprojx @@ -10,7 +10,7 @@ example_arm_compiler_6 0x4 ARM-ADS - 6220000::V6.22::ARMCLANG + 6230000::V6.23::.\ArmCompilerforEmbedded6.24 1 @@ -134,11 +134,11 @@ 0 1 0 - -1 + 4096 1 BIN\UL2CM3.DLL - + "" () @@ -449,7 +449,7 @@ library 0x4 ARM-ADS - 6210000::V6.21::ARMCLANG + 6230000::V6.23::.\ArmCompilerforEmbedded6.24 1 diff --git a/example/gcc_example.uvoptx b/example/gcc_example.uvoptx index 521d24a..1be2004 100644 --- a/example/gcc_example.uvoptx +++ b/example/gcc_example.uvoptx @@ -75,7 +75,7 @@ 1 0 - 1 + 0 7 @@ -280,7 +280,7 @@ 1 0 - 0 + 1 7 diff --git a/example/main.c b/example/main.c index 24ee20f..a5e87a0 100644 --- a/example/main.c +++ b/example/main.c @@ -19,6 +19,7 @@ #include #include #include "perf_counter.h" +#include #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); } } diff --git a/perf_counter.c b/perf_counter.c index ec2b58f..a452771 100644 --- a/perf_counter.c +++ b/perf_counter.c @@ -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) { diff --git a/perf_counter.h b/perf_counter.h index 7e46627..91ad5e5 100644 --- a/perf_counter.h +++ b/perf_counter.h @@ -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; diff --git a/systick_wrapper_gcc.S b/systick_wrapper_gcc.S index 948ce28..6e29df4 100644 --- a/systick_wrapper_gcc.S +++ b/systick_wrapper_gcc.S @@ -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 \ No newline at end of file + bx lr