mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-07-20 19:22:30 -04:00
Add run time stats gathering to the MicroBlaze demo.
This commit is contained in:
parent
1b762ec32d
commit
405a2ca22c
|
@ -77,10 +77,10 @@
|
||||||
*----------------------------------------------------------*/
|
*----------------------------------------------------------*/
|
||||||
#define configUSE_PREEMPTION 1
|
#define configUSE_PREEMPTION 1
|
||||||
#define configUSE_IDLE_HOOK 1
|
#define configUSE_IDLE_HOOK 1
|
||||||
#define configUSE_TICK_HOOK 1
|
#define configUSE_TICK_HOOK 0
|
||||||
#define configCPU_CLOCK_HZ ( XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ ) /* Not actually used in this demo as the timer is set up in main() and uses the peripheral clock, not the CPU clock. */
|
#define configCPU_CLOCK_HZ ( XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ ) /* Not actually used in this demo as the timer is set up in main() and uses the peripheral clock, not the CPU clock. */
|
||||||
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
||||||
#define configMAX_PRIORITIES ( 6 )
|
#define configMAX_PRIORITIES ( 7 )
|
||||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 64 * 1024 ) )
|
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 64 * 1024 ) )
|
||||||
#define configMAX_TASK_NAME_LEN ( 10 )
|
#define configMAX_TASK_NAME_LEN ( 10 )
|
||||||
#define configUSE_TRACE_FACILITY 1
|
#define configUSE_TRACE_FACILITY 1
|
||||||
|
@ -114,7 +114,7 @@ designs will only include on interrupt controller. */
|
||||||
|
|
||||||
/* Software timer definitions. */
|
/* Software timer definitions. */
|
||||||
#define configUSE_TIMERS 1
|
#define configUSE_TIMERS 1
|
||||||
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 4 )
|
||||||
#define configTIMER_QUEUE_LENGTH 10
|
#define configTIMER_QUEUE_LENGTH 10
|
||||||
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
|
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
|
||||||
|
|
||||||
|
@ -127,6 +127,8 @@ to exclude the API function. */
|
||||||
#define INCLUDE_vTaskSuspend 1
|
#define INCLUDE_vTaskSuspend 1
|
||||||
#define INCLUDE_vTaskDelayUntil 1
|
#define INCLUDE_vTaskDelayUntil 1
|
||||||
#define INCLUDE_vTaskDelay 1
|
#define INCLUDE_vTaskDelay 1
|
||||||
|
#define INCLUDE_pcTaskNameGet 1
|
||||||
|
#define INCLUDE_pcTaskNameGet 1
|
||||||
|
|
||||||
#define configASSERT( x ) if( ( x ) == 0 ) { portDISABLE_INTERRUPTS(); for( ;; ); }
|
#define configASSERT( x ) if( ( x ) == 0 ) { portDISABLE_INTERRUPTS(); for( ;; ); }
|
||||||
|
|
||||||
|
@ -143,7 +145,11 @@ prevent the C syntax being included in assembly files. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define configLWIP_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )
|
|
||||||
|
|
||||||
|
/* Networking configuration follows. */
|
||||||
|
|
||||||
|
#define configLWIP_TASK_PRIORITY ( configMAX_PRIORITIES - 4 )
|
||||||
|
|
||||||
/* MAC address configuration. */
|
/* MAC address configuration. */
|
||||||
#define configMAC_ADDR0 0x00
|
#define configMAC_ADDR0 0x00
|
||||||
|
|
|
@ -448,18 +448,6 @@ volatile size_t xFreeHeapSpace;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vApplicationTickHook( void )
|
|
||||||
{
|
|
||||||
/* vApplicationTickHook() will only be called if configUSE_TICK_HOOK is set
|
|
||||||
to 1 in FreeRTOSConfig.h. It executes from an interrupt context so must
|
|
||||||
not use any FreeRTOS API functions that do not end in ...FromISR().
|
|
||||||
|
|
||||||
This simple blinky demo does not use the tick hook, but a tick hook is
|
|
||||||
required to be defined as the blinky and full demos share a
|
|
||||||
FreeRTOSConfig.h header file. */
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
/* This is an application defined callback function used to install the tick
|
/* This is an application defined callback function used to install the tick
|
||||||
interrupt handler. It is provided as an application callback because the kernel
|
interrupt handler. It is provided as an application callback because the kernel
|
||||||
will run on lots of different MicroBlaze and FPGA configurations - not all of
|
will run on lots of different MicroBlaze and FPGA configurations - not all of
|
||||||
|
|
|
@ -70,13 +70,18 @@
|
||||||
* In addition to the standard demo tasks, the following tasks and tests are
|
* In addition to the standard demo tasks, the following tasks and tests are
|
||||||
* defined and/or created within this file:
|
* defined and/or created within this file:
|
||||||
*
|
*
|
||||||
* TCP/IP ("lwIP") task - TBD _RB_
|
* TCP/IP ("lwIP") task - lwIP is used to create a basic web server. The web
|
||||||
|
* server uses server side includes (SSI) to generate tables of task statistics,
|
||||||
|
* and run time statistics (run time statistics show how much processing time
|
||||||
|
* each task has consumed). See
|
||||||
|
* http://www.FreeRTOS.org/Free-RTOS-for-Xilinx-MicroBlaze-on-Spartan-6-FPGA.html
|
||||||
|
* for details on setting up and using the embedded web server.
|
||||||
*
|
*
|
||||||
* "Reg test" tasks - These test the task context switch mechanism by first
|
* "Reg test" tasks - These test the task context switch mechanism by first
|
||||||
* filling the MicroBlaze registers with known values, before checking that each
|
* filling the MicroBlaze registers with known values, before checking that each
|
||||||
* register maintains the value that was written to it as the tasks are switched
|
* register maintains the value that was written to it as the tasks are switched
|
||||||
* in and out. The two register test tasks do not use the same values, and
|
* in and out. The two register test tasks do not use the same values, and
|
||||||
* execute at a very low priority to ensure they are pre-empted regularly.
|
* execute at a very low priority, to ensure they are pre-empted regularly.
|
||||||
*
|
*
|
||||||
* "Check" timer - The check timer period is initially set to five seconds.
|
* "Check" timer - The check timer period is initially set to five seconds.
|
||||||
* The check timer callback function checks that all the standard demo tasks,
|
* The check timer callback function checks that all the standard demo tasks,
|
||||||
|
@ -88,9 +93,15 @@
|
||||||
* indication of the system status: If the LED toggles every five seconds then
|
* indication of the system status: If the LED toggles every five seconds then
|
||||||
* no issues have been discovered. If the LED toggles every 200ms then an issue
|
* no issues have been discovered. If the LED toggles every 200ms then an issue
|
||||||
* has been discovered with at least one task. The last reported issue is
|
* has been discovered with at least one task. The last reported issue is
|
||||||
* latched into the pcStatusMessage variable.
|
* latched into the pcStatusMessage variable, and can also be viewed at the
|
||||||
|
* bottom of the pages served by the embedded web server.
|
||||||
*
|
*
|
||||||
* This file also includes example implementations of the vApplicationTickHook(),
|
* ***NOTE*** This demo uses the standard comtest tasks, which has special
|
||||||
|
* hardware requirements. See
|
||||||
|
* http://www.FreeRTOS.org/Free-RTOS-for-Xilinx-MicroBlaze-on-Spartan-6-FPGA.html
|
||||||
|
* for more information.
|
||||||
|
*
|
||||||
|
* This file also includes example implementations of the
|
||||||
* vApplicationIdleHook(), vApplicationStackOverflowHook(),
|
* vApplicationIdleHook(), vApplicationStackOverflowHook(),
|
||||||
* vApplicationMallocFailedHook(), vApplicationClearTimerInterrupt(), and
|
* vApplicationMallocFailedHook(), vApplicationClearTimerInterrupt(), and
|
||||||
* vApplicationSetupTimerInterrupt() callback (hook) functions.
|
* vApplicationSetupTimerInterrupt() callback (hook) functions.
|
||||||
|
@ -131,11 +142,10 @@
|
||||||
|
|
||||||
/* Priorities at which the various tasks are created. */
|
/* Priorities at which the various tasks are created. */
|
||||||
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||||
#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
||||||
#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
#define mainuIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
|
||||||
#define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
#define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||||
#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
|
@ -210,6 +220,13 @@ static XTmrCtr xTimer0Instance;
|
||||||
/* The 'check' timer, as described at the top of this file. */
|
/* The 'check' timer, as described at the top of this file. */
|
||||||
static xTimerHandle xCheckTimer = NULL;
|
static xTimerHandle xCheckTimer = NULL;
|
||||||
|
|
||||||
|
/* Used in the run time stats calculations. */
|
||||||
|
static unsigned long ulClocksPer10thOfAMilliSecond = 0UL;
|
||||||
|
|
||||||
|
/* Constants used to set up the AXI timer to generate ticks. */
|
||||||
|
static const unsigned char ucTimerCounterNumber = ( unsigned char ) 0U;
|
||||||
|
static const unsigned long ulCounterReloadValue = ( ( XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
int main( void )
|
int main( void )
|
||||||
|
@ -290,6 +307,9 @@ portTickType xExecutionRate = mainNO_ERROR_CHECK_TIMER_PERIOD;
|
||||||
/* This is the callback function used by the 'check' timer, as described
|
/* This is the callback function used by the 'check' timer, as described
|
||||||
in the comments at the top of this file. */
|
in the comments at the top of this file. */
|
||||||
|
|
||||||
|
/* Don't overwrite any errors that have already been latched. */
|
||||||
|
if( pcStatusMessage == NULL )
|
||||||
|
{
|
||||||
/* Check the standard demo tasks are running without error. */
|
/* Check the standard demo tasks are running without error. */
|
||||||
if( xAreGenericQueueTasksStillRunning() != pdTRUE )
|
if( xAreGenericQueueTasksStillRunning() != pdTRUE )
|
||||||
{
|
{
|
||||||
|
@ -349,6 +369,7 @@ portTickType xExecutionRate = mainNO_ERROR_CHECK_TIMER_PERIOD;
|
||||||
{
|
{
|
||||||
pcStatusMessage = "Error: RegTest2\r\n";
|
pcStatusMessage = "Error: RegTest2\r\n";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Store a local copy of the current reg test loop counters. If these have
|
/* Store a local copy of the current reg test loop counters. If these have
|
||||||
not incremented the next time this callback function is executed then the
|
not incremented the next time this callback function is executed then the
|
||||||
|
@ -401,8 +422,6 @@ function below declares as an extern. */
|
||||||
void vApplicationSetupTimerInterrupt( void )
|
void vApplicationSetupTimerInterrupt( void )
|
||||||
{
|
{
|
||||||
portBASE_TYPE xStatus;
|
portBASE_TYPE xStatus;
|
||||||
const unsigned char ucTimerCounterNumber = ( unsigned char ) 0U;
|
|
||||||
const unsigned long ulCounterValue = ( ( XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL );
|
|
||||||
extern void vPortTickISR( void *pvUnused );
|
extern void vPortTickISR( void *pvUnused );
|
||||||
|
|
||||||
/* Initialise the timer/counter. */
|
/* Initialise the timer/counter. */
|
||||||
|
@ -427,7 +446,7 @@ extern void vPortTickISR( void *pvUnused );
|
||||||
XTmrCtr_SetHandler( &xTimer0Instance, ( void * ) vPortTickISR, NULL );
|
XTmrCtr_SetHandler( &xTimer0Instance, ( void * ) vPortTickISR, NULL );
|
||||||
|
|
||||||
/* Set the correct period for the timer. */
|
/* Set the correct period for the timer. */
|
||||||
XTmrCtr_SetResetValue( &xTimer0Instance, ucTimerCounterNumber, ulCounterValue );
|
XTmrCtr_SetResetValue( &xTimer0Instance, ucTimerCounterNumber, ulCounterReloadValue );
|
||||||
|
|
||||||
/* Enable the interrupts. Auto-reload mode is used to generate a
|
/* Enable the interrupts. Auto-reload mode is used to generate a
|
||||||
periodic tick. Note that interrupts are disabled when this function is
|
periodic tick. Note that interrupts are disabled when this function is
|
||||||
|
@ -525,18 +544,6 @@ static long lCheckTimerStarted = pdFALSE;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vApplicationTickHook( void )
|
|
||||||
{
|
|
||||||
/* vApplicationTickHook() will only be called if configUSE_TICK_HOOK is set
|
|
||||||
to 1 in FreeRTOSConfig.h. It executes from an interrupt context so must
|
|
||||||
not use any FreeRTOS API functions that do not end in ...FromISR(). */
|
|
||||||
|
|
||||||
/* Call the periodic timer test, which tests the timer API functions that
|
|
||||||
can be called from an ISR. */
|
|
||||||
vTimerPeriodicISRTests();
|
|
||||||
}
|
|
||||||
/*-----------------------------------------------------------*/
|
|
||||||
|
|
||||||
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump )
|
void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump )
|
||||||
{
|
{
|
||||||
( void ) xRegisterDump;
|
( void ) xRegisterDump;
|
||||||
|
@ -590,19 +597,53 @@ static void prvSetupHardware( void )
|
||||||
|
|
||||||
void vMainConfigureTimerForRunTimeStats( void )
|
void vMainConfigureTimerForRunTimeStats( void )
|
||||||
{
|
{
|
||||||
unsigned long ulRunTimeStatsDivisor;
|
|
||||||
|
|
||||||
/* How many times does the counter counter increment in 10ms? */
|
/* How many times does the counter counter increment in 10ms? */
|
||||||
ulRunTimeStatsDivisor = 0UL / 1000UL; //_RB_
|
ulClocksPer10thOfAMilliSecond = XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / 10000UL;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
unsigned long ulMainGetRunTimeCounterValue( void )
|
unsigned long ulMainGetRunTimeCounterValue( void )
|
||||||
{
|
{
|
||||||
unsigned long ulReturn, ulCurrentCount;
|
unsigned long ulTimerCounts1, ulTimerCounts2, ulTickCount, ulReturn;
|
||||||
|
|
||||||
ulCurrentCount = 0UL;
|
/* NOTE: This can get called from a yield, in which case interrupts are
|
||||||
ulReturn = 0UL;
|
disabled, or from a tick ISR, in which case the effect is the same as if
|
||||||
|
interrupts were disabled. In either case, it is going to run atomically. */
|
||||||
|
|
||||||
|
/* The timer is in down count mode. How many clocks have passed since it
|
||||||
|
was last reloaded? */
|
||||||
|
ulTimerCounts1 = ulCounterReloadValue - XTmrCtr_GetValue( &xTimer0Instance, ucTimerCounterNumber );
|
||||||
|
|
||||||
|
/* How many times has it overflowed? */
|
||||||
|
ulTickCount = xTaskGetTickCountFromISR();
|
||||||
|
|
||||||
|
/* If this is being called from a yield, has the counter overflowed since
|
||||||
|
it was read? If that is the case then ulTickCounts will need incrementing
|
||||||
|
again as it will not yet have been incremented from the tick interrupt. */
|
||||||
|
ulTimerCounts2 = ulCounterReloadValue - XTmrCtr_GetValue( &xTimer0Instance, ucTimerCounterNumber );
|
||||||
|
if( ulTimerCounts2 < ulTimerCounts1 )
|
||||||
|
{
|
||||||
|
/* There is a tick interrupt pending but the tick count not yet
|
||||||
|
incremented. */
|
||||||
|
ulTickCount++;
|
||||||
|
|
||||||
|
/* Use the second timer reading. */
|
||||||
|
ulTimerCounts1 = ulTimerCounts2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert the tick count into tenths of a millisecond. THIS ASSUMES
|
||||||
|
configTICK_RATE_HZ is 1000! */
|
||||||
|
ulReturn = ( ulTickCount * 10UL );
|
||||||
|
|
||||||
|
/* Add on the number of tenths of a millisecond that have passed since the
|
||||||
|
tick count last got updated. */
|
||||||
|
ulReturn += ( ulTimerCounts1 / ulClocksPer10thOfAMilliSecond );
|
||||||
|
|
||||||
|
/* Some crude rounding. */
|
||||||
|
if( ( ulTimerCounts1 % ulClocksPer10thOfAMilliSecond ) > ( ulClocksPer10thOfAMilliSecond >> 1UL ) )
|
||||||
|
{
|
||||||
|
ulReturn++;
|
||||||
|
}
|
||||||
|
|
||||||
return ulReturn;
|
return ulReturn;
|
||||||
}
|
}
|
||||||
|
@ -610,7 +651,18 @@ unsigned long ulReturn, ulCurrentCount;
|
||||||
|
|
||||||
char *pcMainGetTaskStatusMessage( void )
|
char *pcMainGetTaskStatusMessage( void )
|
||||||
{
|
{
|
||||||
return ( char * ) pcStatusMessage;
|
char * pcReturn;
|
||||||
|
|
||||||
|
if( pcStatusMessage == NULL )
|
||||||
|
{
|
||||||
|
pcReturn = ( char * ) "OK";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pcReturn = ( char * ) pcStatusMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pcReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue