summaryrefslogtreecommitdiff
path: root/FreeRTOS
diff options
context:
space:
mode:
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2013-06-25 10:44:44 +0000
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2013-06-25 10:44:44 +0000
commitf69b82e91ad84c23abeaffada7ca14d06e4edc7a (patch)
tree642974a494a1a21f77762bc6d6800602a3df7189 /FreeRTOS
parent1b35701c1bfc1cb9741317346f0a3414031fce86 (diff)
downloadfreertos-f69b82e91ad84c23abeaffada7ca14d06e4edc7a.tar.gz
Re-implement the LPC18xx and SmartFusion2 run time stats implementation to use the free running Cortex-M cycle counter in place of the systick.
Correct the run-time stats counter implementation in the RZ demo. Guard against run time counters going backwards in tasks.c. git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@1946 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
Diffstat (limited to 'FreeRTOS')
-rw-r--r--FreeRTOS/Demo/CORTEX_A9_RZ_R7S72100_IAR_DS-5/Source/FreeRTOS_tick_config.c3
-rw-r--r--FreeRTOS/Demo/CORTEX_SmartFusion2_M2S050_SoftConsole/RTOSDemo/RunTimeStatsTimer.c81
-rw-r--r--FreeRTOS/Source/tasks.c17
3 files changed, 57 insertions, 44 deletions
diff --git a/FreeRTOS/Demo/CORTEX_A9_RZ_R7S72100_IAR_DS-5/Source/FreeRTOS_tick_config.c b/FreeRTOS/Demo/CORTEX_A9_RZ_R7S72100_IAR_DS-5/Source/FreeRTOS_tick_config.c
index 71c755999..aca9378da 100644
--- a/FreeRTOS/Demo/CORTEX_A9_RZ_R7S72100_IAR_DS-5/Source/FreeRTOS_tick_config.c
+++ b/FreeRTOS/Demo/CORTEX_A9_RZ_R7S72100_IAR_DS-5/Source/FreeRTOS_tick_config.c
@@ -141,7 +141,8 @@ unsigned long ulValueNow;
ulLastCounterValue = ulValueNow;
/* There is no prescale on the counter, so simulate in software. */
- ulValueNow >>= runtimeCLOCK_SCALE_SHIFT + ( runtimeOVERFLOW_BIT * ulOverflows );
+ ulValueNow >>= runtimeCLOCK_SCALE_SHIFT;
+ ulValueNow += ( runtimeOVERFLOW_BIT * ulOverflows );
return ulValueNow;
}
diff --git a/FreeRTOS/Demo/CORTEX_SmartFusion2_M2S050_SoftConsole/RTOSDemo/RunTimeStatsTimer.c b/FreeRTOS/Demo/CORTEX_SmartFusion2_M2S050_SoftConsole/RTOSDemo/RunTimeStatsTimer.c
index 0ce8bc630..ba195276f 100644
--- a/FreeRTOS/Demo/CORTEX_SmartFusion2_M2S050_SoftConsole/RTOSDemo/RunTimeStatsTimer.c
+++ b/FreeRTOS/Demo/CORTEX_SmartFusion2_M2S050_SoftConsole/RTOSDemo/RunTimeStatsTimer.c
@@ -74,65 +74,72 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
-#include "task.h"
/* Utility functions to implement run time stats on Cortex-M CPUs. The collected
run time data can be viewed through the CLI interface. See the following URL for
more information on run time stats:
http://www.freertos.org/rtos-run-time-stats.html */
-/* Used in the run time stats calculations. */
-static uint32_t ulClocksPer10thOfAMilliSecond = 0UL;
+/* Addresses of registers in the Cortex-M debug hardware. */
+#define rtsDWT_CYCCNT ( *( ( unsigned long * ) 0xE0001004 ) )
+#define rtsDWT_CONTROL ( *( ( unsigned long * ) 0xE0001000 ) )
+#define rtsSCB_DEMCR ( *( ( unsigned long * ) 0xE000EDFC ) )
+#define rtsTRCENA_BIT ( 0x01000000UL )
+#define rtsCOUNTER_ENABLE_BIT ( 0x01UL )
+
+/* Simple shift divide for scaling to avoid an overflow occurring too soon. The
+number of bits to shift depends on the clock speed. */
+#define runtimeSLOWER_CLOCK_SPEEDS ( 70000000UL )
+#define runtimeSHIFT_13 13
+#define runtimeOVERFLOW_BIT_13 ( 1UL << ( 32UL - runtimeSHIFT_13 ) )
+#define runtimeSHIFT_14 14
+#define runtimeOVERFLOW_BIT_14 ( 1UL << ( 32UL - runtimeSHIFT_14 ) )
+/*-----------------------------------------------------------*/
void vConfigureTimerForRunTimeStats( void )
{
- /* How many clocks are there per tenth of a millisecond? */
- ulClocksPer10thOfAMilliSecond = configCPU_CLOCK_HZ / 10000UL;
+ /* Enable TRCENA. */
+ rtsSCB_DEMCR = rtsSCB_DEMCR | rtsTRCENA_BIT;
+
+ /* Reset counter. */
+ rtsDWT_CYCCNT = 0;
+
+ /* Enable counter. */
+ rtsDWT_CONTROL = rtsDWT_CONTROL | rtsCOUNTER_ENABLE_BIT;
}
/*-----------------------------------------------------------*/
uint32_t ulGetRunTimeCounterValue( void )
{
-uint32_t ulSysTickCounts, ulTickCount, ulReturn;
-const uint32_t ulSysTickReloadValue = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
-volatile uint32_t * const pulCurrentSysTickCount = ( ( volatile uint32_t *) 0xe000e018 );
-volatile uint32_t * const pulInterruptCTRLState = ( ( volatile uint32_t *) 0xe000ed04 );
-const uint32_t ulSysTickPendingBit = 0x04000000UL;
-
- /* NOTE: There are potentially race conditions here. However, it is used
- anyway to keep the examples simple, and to avoid reliance on a separate
- timer peripheral. */
-
-
- /* The SysTick is a down counter. How many clocks have passed since it was
- last reloaded? */
- ulSysTickCounts = ulSysTickReloadValue - *pulCurrentSysTickCount;
+static unsigned long ulLastCounterValue = 0UL, ulOverflows = 0;
+unsigned long ulValueNow;
- /* How many times has it overflowed? */
- ulTickCount = xTaskGetTickCountFromISR();
+ ulValueNow = rtsDWT_CYCCNT;
- /* Is there a SysTick interrupt pending? */
- if( ( *pulInterruptCTRLState & ulSysTickPendingBit ) != 0UL )
+ /* Has the value overflowed since it was last read. */
+ if( ulValueNow < ulLastCounterValue )
{
- /* There is a SysTick interrupt pending, so the SysTick has overflowed
- but the tick count not yet incremented. */
- ulTickCount++;
-
- /* Read the SysTick again, as the overflow might have occurred since
- it was read last. */
- ulSysTickCounts = ulSysTickReloadValue - *pulCurrentSysTickCount;
+ ulOverflows++;
}
+ ulLastCounterValue = ulValueNow;
- /* Convert the tick count into tenths of a millisecond. THIS ASSUMES
- configTICK_RATE_HZ is 1000! */
- ulReturn = ( ulTickCount * 10UL ) ;
+ /* Cannot use configCPU_CLOCK_HZ directly as it may itself not be a constant
+ but instead map to a variable that holds the clock speed. */
- /* Add on the number of tenths of a millisecond that have passed since the
- tick count last got updated. */
- ulReturn += ( ulSysTickCounts / ulClocksPer10thOfAMilliSecond );
+ /* There is no prescale on the counter, so simulate in software. */
+ if( configCPU_CLOCK_HZ < runtimeSLOWER_CLOCK_SPEEDS )
+ {
+ ulValueNow >>= runtimeSHIFT_13;
+ ulValueNow += ( runtimeOVERFLOW_BIT_13 * ulOverflows );
+ }
+ else
+ {
+ ulValueNow >>= runtimeSHIFT_14;
+ ulValueNow += ( runtimeOVERFLOW_BIT_14 * ulOverflows );
+ }
- return ulReturn;
+ return ulValueNow;
}
/*-----------------------------------------------------------*/
diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c
index 91358b8a9..abe344066 100644
--- a/FreeRTOS/Source/tasks.c
+++ b/FreeRTOS/Source/tasks.c
@@ -1843,12 +1843,17 @@ void vTaskSwitchContext( void )
ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
#endif
- /* Add the amount of time the task has been running to the accumulated
- time so far. The time the task started running was stored in
- ulTaskSwitchedInTime. Note that there is no overflow protection here
- so count values are only valid until the timer overflows. Generally
- this will be about 1 hour assuming a 1uS timer increment. */
- pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
+ /* Add the amount of time the task has been running to the
+ accumulated time so far. The time the task started running was
+ stored in ulTaskSwitchedInTime. Note that there is no overflow
+ protection here so count values are only valid until the timer
+ overflows. The guard against negative values is to protect
+ against suspect run time stat counter implementations - which
+ are provided by the application, not the kernel. */
+ if( ulTotalRunTime > ulTaskSwitchedInTime )
+ {
+ pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
+ }
ulTaskSwitchedInTime = ulTotalRunTime;
}
#endif /* configGENERATE_RUN_TIME_STATS */