*/\r
\r
/* ****************************************************************************\r
- * This project includes a lot of tasks and tests and is therefore complex.\r
- * If you would prefer a much simpler project to get started with then select\r
- * the 'Blinky' build configuration within the Embedded Workbench IDE.\r
+ * This project includes a lot of demo and test tasks, and is therefore complex.\r
+ * If you would prefer a much simpler project to get started with, then select\r
+ * the 'Blinky' build configuration within the SDK Eclipse IDE.\r
* ****************************************************************************\r
*\r
- * Creates all the demo application tasks, then starts the scheduler. The web\r
- * documentation provides more details of the standard demo application tasks,\r
- * which provide no particular functionality but do provide a good example of\r
- * how to use the FreeRTOS API. The tasks defined in flop.c are included in the\r
- * set of standard demo tasks to ensure the floating point unit gets some\r
- * exercise.\r
+ * main() creates all the demo application tasks, then starts the scheduler. \r
+ * The web documentation provides more details of the standard demo application \r
+ * tasks, which provide no particular functionality, but do provide a good \r
+ * example of how to use the FreeRTOS API. \r
*\r
* In addition to the standard demo tasks, the following tasks and tests are\r
* defined and/or created within this file:\r
*\r
- * Webserver ("uIP") task - This serves a number of dynamically generated WEB\r
- * pages to a standard WEB browser. The IP and MAC addresses are configured by\r
- * constants defined at the bottom of FreeRTOSConfig.h. Use either a standard\r
- * Ethernet cable to connect through a hug, or a cross over (point to point)\r
- * cable to connect directly. Ensure the IP address used is compatible with the\r
- * IP address of the machine running the browser - the easiest way to achieve\r
- * this is to ensure the first three octets of the IP addresses are the same.\r
+ * Webserver ("lwIP") task - TBD _RB_\r
*\r
* "Reg test" tasks - These fill the registers with known values, then check\r
* that each register still contains its expected value. Each task uses\r
* test loop. A register containing an unexpected value is indicative of an\r
* error in the context switching mechanism and will result in a branch to a\r
* null loop - which in turn will prevent the check variable from incrementing\r
- * any further and allow the check task (described below) to determine that an\r
+ * any further and allow the check timer (described below) to determine that an\r
* error has occurred. The nature of the reg test tasks necessitates that they\r
* are written in assembly code.\r
*\r
- * "Check" task - This only executes every five seconds but has a high priority\r
- * to ensure it gets processor time. Its main function is to check that all the\r
- * standard demo tasks are still operational. While no errors have been\r
- * discovered the check task will toggle LED 5 every 5 seconds - the toggle\r
- * rate increasing to 200ms being a visual indication that at least one task has\r
- * reported unexpected behaviour.\r
+ * "Check" timer - The check timer period is initially set to five seconds. \r
+ * The check timer callback function checks that all the standard demo tasks are \r
+ * functioning as expected, without error. If an error is discovered in any \r
+ * standard demo task, then the check timer period is shortened to 200ms. The\r
+ * check timer callback function also toggles an LED each time it is called. \r
+ * Therefore, if the LED toggles every five seconds, all the tasks are\r
+ * functioning as expected, without any error conditions being detected. If the\r
+ * LED toggles every 200ms then an error has been discovered in at least one\r
+ * task. \r
*\r
- * "High frequency timer test" - A high frequency periodic interrupt is\r
- * generated using a timer - the interrupt is assigned a priority above\r
- * configMAX_SYSCALL_INTERRUPT_PRIORITY so should not be effected by anything\r
- * the kernel is doing. The frequency and priority of the interrupt, in\r
- * combination with other standard tests executed in this demo, should result\r
- * in interrupts nesting at least 3 and probably 4 deep. This test is only\r
- * included in build configurations that have the optimiser switched on. In\r
- * optimised builds the count of high frequency ticks is used as the time base\r
- * for the run time stats.\r
- *\r
- * *NOTE 1* If LED5 is toggling every 5 seconds then all the demo application\r
- * tasks are executing as expected and no errors have been reported in any\r
- * tasks. The toggle rate increasing to 200ms indicates that at least one task\r
- * has reported unexpected behaviour.\r
- *\r
- * *NOTE 2* vApplicationSetupTimerInterrupt() is called by the kernel to let\r
- * the application set up a timer to generate the tick interrupt. In this\r
- * example a compare match timer is used for this purpose.\r
- *\r
- * *NOTE 3* The CPU must be in Supervisor mode when the scheduler is started.\r
- * The PowerON_Reset_PC() supplied in resetprg.c with this demo has\r
- * Change_PSW_PM_to_UserMode() commented out to ensure this is the case.\r
- *\r
- * *NOTE 4* The IntQueue common demo tasks test interrupt nesting and make use\r
- * of all the 8bit timers (as two cascaded 16bit units).\r
-*/\r
+ * This file also includes example implementations of the vApplicationTickHook(),\r
+ * vApplicationIdleHook(), vApplicationStackOverflowHook(),\r
+ * vApplicationMallocFailedHook(), vApplicationClearTimerInterrupt(), and\r
+ * vApplicationSetupTimerInterrupt() callback (hook) functions.\r
+ */\r
\r
/* Standard includes. */\r
#include <string.h>\r
#include <stdio.h>\r
\r
/* BSP includes. */\r
-#include "xenv_standalone.h"\r
#include "xtmrctr.h"\r
-#include "xil_exception.h"\r
-#include "microblaze_exceptions_g.h"\r
-#include "xgpio.h"\r
\r
/* Kernel includes. */\r
#include "FreeRTOS.h"\r
#include "flop.h"\r
#include "dynamic.h"\r
#include "comtest_strings.h"\r
-\r
-#define xPrintf( x )\r
+#include "TimerDemo.h"\r
\r
/* Priorities at which the tasks are created. */\r
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
baud rate parameter. */\r
#define mainCOM_TEST_BAUD_RATE ( XPAR_RS232_UART_1_BAUDRATE )\r
\r
+#define mainTIMER_TEST_PERIOD ( 20 )\r
+\r
/*\r
* vApplicationMallocFailedHook() will only be called if\r
* configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook\r
\r
static void prvSetupHardware( void );\r
\r
-/*\r
- * Contains the implementation of the WEB server.\r
- */\r
-//_RB_extern void vuIP_Task( void *pvParameters );\r
\r
/*-----------------------------------------------------------*/\r
\r
\r
int main( void )\r
{\r
+ /* *************************************************************************\r
+ This project includes a lot of demo and test tasks, and is therefore complex.\r
+ If you would prefer a much simpler project to get started with, then select\r
+ the 'Blinky' build configuration within the SDK Eclipse IDE.\r
+ ***************************************************************************/\r
+\r
/* Configure the interrupt controller, LED outputs and button inputs. */\r
prvSetupHardware();\r
\r
xTaskCreate( vRegisterTest1, ( const signed char * const ) "RegTst1", configMINIMAL_STACK_SIZE, ( void * ) 0, tskIDLE_PRIORITY, NULL );\r
xTaskCreate( vRegisterTest2, ( const signed char * const ) "RegTst2", configMINIMAL_STACK_SIZE, ( void * ) 0, tskIDLE_PRIORITY, NULL );\r
\r
- /* The web server task. */\r
-//_RB_ xTaskCreate( vuIP_Task, "uIP", mainuIP_STACK_SIZE, NULL, mainuIP_TASK_PRIORITY, NULL );\r
-\r
/* Create the standard demo tasks. */\r
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
vCreateBlockTimeTasks();\r
vStartQueuePeekTasks();\r
vStartRecursiveMutexTasks();\r
vStartComTestStringsTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );\r
+ vStartDynamicPriorityTasks();\r
+ vStartTimerDemoTask( mainTIMER_TEST_PERIOD );\r
\r
/* Note - the set of standard demo tasks contains two versions of\r
vStartMathTasks.c. One is defined in flop.c, and uses double precision\r
until after the scheduler has been started. */\r
xCheckTimer = xTimerCreate( ( const signed char * ) "Check timer", mainNO_ERROR_CHECK_TIMER_PERIOD, pdTRUE, ( void * ) 0, vCheckTimerCallback );\r
\r
- /* Ensure the check timer will start running as soon as the scheduler\r
- starts. The block time is set to 0 (mainDONT_BLOCK), but would be\r
- ingnored at this point anyway as block times can only be specified when\r
- the scheduler is running. */\r
- xTimerStart( xCheckTimer, mainDONT_BLOCK );\r
-\r
/* Start the tasks running. */\r
vTaskStartScheduler();\r
\r
extern unsigned long ulRegTest1CycleCount, ulRegTest2CycleCount;\r
static volatile unsigned long ulLastRegTest1CycleCount = 0UL, ulLastRegTest2CycleCount = 0UL;\r
static long lErrorAlreadyLatched = pdFALSE;\r
+portTickType xExecutionRate = mainNO_ERROR_CHECK_TIMER_PERIOD;\r
\r
/* This is the callback function used by the 'check' timer, as described\r
at the top of this file. */\r
rate at which mainCHECK_LED flashes to give visual feedback that an error\r
has occurred. */\r
pcStatusMessage = "Error: GenQueue";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
+ else if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
{\r
pcStatusMessage = "Error: QueuePeek\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
+ else if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
{\r
pcStatusMessage = "Error: BlockQueue\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )\r
+ else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )\r
{\r
pcStatusMessage = "Error: BlockTime\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
+ else if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
{\r
pcStatusMessage = "Error: SemTest\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- if( xArePollingQueuesStillRunning() != pdTRUE )\r
+ else if( xArePollingQueuesStillRunning() != pdTRUE )\r
{\r
pcStatusMessage = "Error: PollQueue\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- if( xIsCreateTaskStillRunning() != pdTRUE )\r
+ else if( xIsCreateTaskStillRunning() != pdTRUE )\r
{\r
pcStatusMessage = "Error: Death\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
+ else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
{\r
pcStatusMessage = "Error: RecMutex\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- if( xAreMathsTaskStillRunning() != pdPASS )\r
+ else if( xAreMathsTaskStillRunning() != pdPASS )\r
{\r
pcStatusMessage = "Error: Flop\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- if( xAreComTestTasksStillRunning() != pdPASS )\r
+ else if( xAreComTestTasksStillRunning() != pdPASS )\r
{\r
pcStatusMessage = "Error: Comtest\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- /* Check the reg test tasks are still cycling. They will stop incrementing\r
- their loop counters if they encounter an error. */\r
- if( ulRegTest1CycleCount == ulLastRegTest1CycleCount )\r
+ else if( xAreDynamicPriorityTasksStillRunning() != pdPASS )\r
{\r
+ pcStatusMessage = "Error: Dynamic\r\n";\r
+ }\r
+ else if( xAreTimerDemoTasksStillRunning( xExecutionRate ) != pdTRUE )\r
+ {\r
+ pcStatusMessage = "Error: TimerDemo";\r
+ }\r
+ else if( ulRegTest1CycleCount == ulLastRegTest1CycleCount )\r
+ {\r
+ /* Check the reg test tasks are still cycling. They will stop\r
+ incrementing their loop counters if they encounter an error. */\r
pcStatusMessage = "Error: RegTest1\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
-\r
- if( ulRegTest2CycleCount == ulLastRegTest2CycleCount )\r
+ else if( ulRegTest2CycleCount == ulLastRegTest2CycleCount )\r
{\r
pcStatusMessage = "Error: RegTest2\r\n";\r
- xPrintf( pcStatusMessage );\r
}\r
\r
ulLastRegTest1CycleCount = ulRegTest1CycleCount;\r
This is called from a timer callback so must not attempt to block. */
xTimerChangePeriod( xTimer, mainERROR_CHECK_TIMER_PERIOD, mainDONT_BLOCK );\r
\r
+ /* Update the xExecutionRate variable as the rate at which this\r
+ callback is executed has to be passed into the\r
+ xAreTimerDemoTasksStillRunning() function. */\r
+ xExecutionRate = mainERROR_CHECK_TIMER_PERIOD;\r
+\r
/* Just to ensure the timer period is not changed on each execution\r
of the callback. */
lErrorAlreadyLatched = pdTRUE;\r
{\r
portBASE_TYPE xStatus;\r
const unsigned char ucTimerCounterNumber = ( unsigned char ) 0U;\r
-//const unsigned long ulCounterValue = ( ( XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL );\r
-const unsigned long ulCounterValue = ( ( ( XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL ) ) * 2UL; //_RB_ there is a clock set up incorrectly somwehre, the *2 should not be required.\r
+const unsigned long ulCounterValue = ( ( XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL );\r
extern void vTickISR( void *pvUnused );\r
\r
/* Initialise the timer/counter. */\r
{\r
unsigned long ulCSR;\r
\r
- /* Increment the RTOS tick - this might cause a task to unblock. */\r
- vTaskIncrementTick();\r
-\r
/* Clear the timer interrupt */\r
ulCSR = XTmrCtr_GetControlStatusReg( XPAR_AXI_TIMER_0_BASEADDR, 0 );\r
XTmrCtr_SetControlStatusReg( XPAR_AXI_TIMER_0_BASEADDR, 0, ulCSR );\r
of this file. */\r
void vApplicationIdleHook( void )\r
{\r
+static long lCheckTimerStarted = pdFALSE;\r
+\r
+ if( lCheckTimerStarted == pdFALSE )\r
+ {\r
+ xTimerStart( xCheckTimer, mainDONT_BLOCK ); //_RB_ comment why this is done here.\r
+ lCheckTimerStarted = pdTRUE;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationTickHook( void )\r
+{\r
+ /* Call the periodic timer test, which tests the timer API functions that\r
+ can be called from an ISR. */\r
+ vTimerPeriodicISRTests();\r
}\r
/*-----------------------------------------------------------*/\r
\r