2 FreeRTOS.org V4.7.0 - Copyright (C) 2003-2007 Richard Barry.
\r
4 This file is part of the FreeRTOS.org distribution.
\r
6 FreeRTOS.org is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 FreeRTOS.org is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with FreeRTOS.org; if not, write to the Free Software
\r
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 A special exception to the GPL can be applied should you wish to distribute
\r
21 a combined work that includes FreeRTOS.org, without being obliged to provide
\r
22 the source code for any proprietary components. See the licensing section
\r
23 of http://www.FreeRTOS.org for full details of how and when the exception
\r
26 ***************************************************************************
\r
27 See http://www.FreeRTOS.org for documentation, latest information, license
\r
28 and contact details. Please ensure to read the configuration and relevant
\r
29 port sections of the online documentation.
\r
31 Also see http://www.SafeRTOS.com a version that has been certified for use
\r
32 in safety critical systems, plus commercial licensing, development and
\r
34 ***************************************************************************
\r
38 * Creates all the demo application tasks, then starts the scheduler. The WEB
\r
39 * documentation provides more details of the standard demo application tasks.
\r
40 * In addition to the standard demo tasks, the following tasks and tests are
\r
41 * defined and/or created within this file:
\r
43 * "Fast Interrupt Test" - A high frequency periodic interrupt is generated
\r
44 * using a free running timer to demonstrate the use of the
\r
45 * configKERNEL_INTERRUPT_PRIORITY configuration constant. The interrupt
\r
46 * service routine measures the number of processor clocks that occur between
\r
47 * each interrupt - and in so doing measures the jitter in the interrupt timing.
\r
48 * The maximum measured jitter time is latched in the ulMaxJitter variable, and
\r
49 * displayed on the LCD display by the 'LCD' task as described below. The
\r
50 * fast interrupt is configured and handled in the timertest.c source file.
\r
52 * "LCD" task - the LCD task is a 'gatekeeper' task. It is the only task that
\r
53 * is permitted to access the display directly. Other tasks wishing to write a
\r
54 * message to the LCD send the message on a queue to the LCD task instead of
\r
55 * accessing the LCD themselves. The LCD task just blocks on the queue waiting
\r
56 * for messages - waking and displaying the messages as they arrive.
\r
58 * "Check" task - This only executes every three seconds but has the highest
\r
59 * priority so is guaranteed to get processor time. Its main function is to
\r
60 * check that all the standard demo tasks are still operational. Should any
\r
61 * unexpected behaviour within a demo task be discovered the check task will
\r
62 * write an error to the LCD (via the LCD task). If all the demo tasks are
\r
63 * executing with their expected behaviour then the check task writes the
\r
64 * maximum jitter time to the LCD (as described above) - again via the LCD task.
\r
66 * "Register test" tasks - These tasks are used in part to test the kernel port.
\r
67 * They set each processor register to a known value, then check that the
\r
68 * register still contains that value. Each of the tasks sets the registers
\r
69 * to different values, and will get swapping in and out between setting and
\r
70 * then subsequently checking the register values. Discovery of an incorrect
\r
71 * value would be indicative of an error in the task switching mechanism.
\r
74 /* Standard includes. */
\r
77 /* Scheduler includes. */
\r
78 #include "FreeRTOS.h"
\r
82 /* Demo application includes. */
\r
83 #include "partest.h"
\r
84 #include "integer.h"
\r
85 #include "blocktim.h"
\r
87 #include "semtest.h"
\r
88 #include "GenQTest.h"
\r
91 #include "comtest2.h"
\r
92 #include "timertest.h"
\r
94 #pragma config FPLLMUL = MUL_18, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
\r
95 #pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_2
\r
97 /*-----------------------------------------------------------*/
\r
99 /* The rate at which the LED controlled by the 'check' task will flash when no
\r
100 errors have been detected. */
\r
101 #define mainNO_ERROR_PERIOD ( 3000 / portTICK_RATE_MS )
\r
103 /* The rate at which the LED controlled by the 'check' task will flash when an
\r
104 error has been detected. */
\r
105 #define mainERROR_PERIOD ( 500 )
\r
107 /* The priorities of the various demo application tasks. */
\r
108 #define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 4 )
\r
109 #define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
110 #define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )
\r
111 #define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
\r
112 #define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
\r
113 #define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
\r
115 /* The LED controlled by the 'check' task. */
\r
116 #define mainCHECK_LED ( 7 )
\r
118 /* The LED used by the comtest tasks. mainCOM_TEST_LED + 1 is also used.
\r
119 See the comtest.c file for more information. */
\r
120 #define mainCOM_TEST_LED ( 4 )
\r
122 /* Baud rate used by the comtest tasks. */
\r
123 #define mainCOM_TEST_BAUD_RATE ( 115200 )
\r
126 #define mainDONT_WAIT ( 0 )
\r
128 /* Dimension the buffer used to hold the value of the maximum jitter time when
\r
129 it is converted to a string. */
\r
130 #define mainMAX_STRING_LENGTH ( 20 )
\r
132 /* The frequency at which the "fast interrupt test" interrupt will occur. */
\r
133 #define mainTEST_INTERRUPT_FREQUENCY ( 20000 )
\r
135 /* The number of timer clocks we expect to occur between each "fast
\r
136 interrupt test" interrupt. */
\r
137 #define mainEXPECTED_CLOCKS_BETWEEN_INTERRUPTS ( ( configCPU_CLOCK_HZ >> 1 ) / mainTEST_INTERRUPT_FREQUENCY )
\r
139 /* The number of nano seconds between each core clock. */
\r
140 #define mainNS_PER_CLOCK ( ( unsigned portLONG ) ( ( 1.0 / ( double ) ( configCPU_CLOCK_HZ >> 1 ) ) * 1000000000.0 ) )
\r
142 /*-----------------------------------------------------------*/
\r
145 * Setup the processor ready for the demo.
\r
147 static void prvSetupHardware( void );
\r
150 * Implements the 'check' task functionality as described at the top of this
\r
153 static void prvCheckTask( void *pvParameters ) __attribute__((noreturn));
\r
156 * Tasks that test the context switch mechanism by filling the processor
\r
157 * registers with known values, then checking that the values contained
\r
158 * within the registers is as expected. The tasks are likely to get swapped
\r
159 * in and out between setting the register values and checking the register
\r
161 static void prvTestTask1( void *pvParameters );
\r
162 static void prvTestTask2( void *pvParameters );
\r
164 /*-----------------------------------------------------------*/
\r
166 /* The queue used to send messages to the LCD task. */
\r
167 static xQueueHandle xLCDQueue;
\r
169 /* Flag used by prvTestTask1() and prvTestTask2() to indicate their status
\r
171 unsigned portLONG ulStatus1 = pdPASS;
\r
173 /* Variables incremented by prvTestTask1() and prvTestTask2() respectively on
\r
174 each iteration of their function. This is used to detect either task stopping
\r
175 their execution.. */
\r
176 unsigned portLONG ulRegTest1Cycles = 0, ulRegTest2Cycles = 0;
\r
178 /*-----------------------------------------------------------*/
\r
182 * Create the demo tasks then start the scheduler.
\r
186 /* Configure any hardware required for this demo. */
\r
187 prvSetupHardware();
\r
189 /* Create the LCD task - this returns the queue to use when writing
\r
190 messages to the LCD. */
\r
191 xLCDQueue = xStartLCDTask();
\r
193 /* Create all the other standard demo tasks. */
\r
194 vStartLEDFlashTasks( tskIDLE_PRIORITY );
\r
195 vCreateBlockTimeTasks();
\r
196 vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
\r
197 vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );
\r
198 vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );
\r
199 vStartQueuePeekTasks();
\r
200 vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );
\r
202 /* Create the tasks defined within this file. */
\r
203 xTaskCreate( prvTestTask1, "Tst1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
\r
204 xTaskCreate( prvTestTask2, "Tst2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
\r
206 /* prvCheckTask uses sprintf so requires more stack. */
\r
207 xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE * 2, NULL, mainCHECK_TASK_PRIORITY, NULL );
\r
209 /* Setup the high frequency, high priority, timer test. */
\r
210 vSetupTimerTest( mainTEST_INTERRUPT_FREQUENCY );
\r
212 /* Finally start the scheduler. */
\r
213 vTaskStartScheduler();
\r
215 /* Will only reach here if there is insufficient heap available to start
\r
219 /*-----------------------------------------------------------*/
\r
221 static void prvTestTask1( void *pvParameters )
\r
223 extern void vRegTest1( unsigned long * );
\r
227 /* Perform the register test function. */
\r
228 vRegTest1( &ulStatus1 );
\r
230 /* Increment the counter so the check task knows we are still
\r
232 ulRegTest1Cycles++;
\r
235 /*-----------------------------------------------------------*/
\r
237 static void prvTestTask2( void *pvParameters )
\r
239 extern void vRegTest2( unsigned long * );
\r
243 /* Perform the register test function. */
\r
244 vRegTest2( &ulStatus1 );
\r
246 /* Increment the counter so the check task knows we are still
\r
248 ulRegTest2Cycles++;
\r
251 /*-----------------------------------------------------------*/
\r
253 static void prvSetupHardware( void )
\r
255 /* Set the system and peripheral bus speeds and enable the program cache*/
\r
256 SYSTEMConfigPerformance( configCPU_CLOCK_HZ );
\r
258 /* Setup to use the external interrupt controller. */
\r
259 INTEnableSystemMultiVectoredInt();
\r
261 portDISABLE_INTERRUPTS();
\r
263 /* Setup the digital IO for the LED's. */
\r
264 vParTestInitialise();
\r
266 /*-----------------------------------------------------------*/
\r
268 static void prvCheckTask( void *pvParameters )
\r
270 unsigned portLONG ulLastRegTest1Value = 0, ulLastRegTest2Value = 0, ulTicksToWait = mainNO_ERROR_PERIOD;
\r
271 portTickType xLastExecutionTime;
\r
273 /* Buffer into which the maximum jitter time is written as a string. */
\r
274 static portCHAR cStringBuffer[ mainMAX_STRING_LENGTH ];
\r
276 /* The maximum jitter time measured by the fast interrupt test. */
\r
277 extern unsigned portLONG ulMaxJitter ;
\r
278 xLCDMessage xMessage = { ( 200 / portTICK_RATE_MS ), cStringBuffer };
\r
280 /* Initialise the variable used to control our iteration rate prior to
\r
282 xLastExecutionTime = xTaskGetTickCount();
\r
286 /* Wait until it is time to run the tests again. */
\r
287 vTaskDelayUntil( &xLastExecutionTime, ulTicksToWait );
\r
289 /* Has either register check 1 or 2 task discovered an error? */
\r
290 if( ulStatus1 != pdPASS )
\r
292 ulTicksToWait = mainERROR_PERIOD;
\r
293 xMessage.pcMessage = "Error: Reg test1";
\r
296 /* Check that the register test 1 task is still running. */
\r
297 if( ulLastRegTest1Value == ulRegTest1Cycles )
\r
299 ulTicksToWait = mainERROR_PERIOD;
\r
300 xMessage.pcMessage = "Error: Reg test2";
\r
302 ulLastRegTest1Value = ulRegTest1Cycles;
\r
305 /* Check that the register test 2 task is still running. */
\r
306 if( ulLastRegTest2Value == ulRegTest2Cycles )
\r
308 ulTicksToWait = mainERROR_PERIOD;
\r
309 xMessage.pcMessage = "Error: Reg test3";
\r
311 ulLastRegTest2Value = ulRegTest2Cycles;
\r
314 /* Have any of the standard demo tasks detected an error in their
\r
316 if( xAreGenericQueueTasksStillRunning() != pdTRUE )
\r
318 ulTicksToWait = mainERROR_PERIOD;
\r
319 xMessage.pcMessage = "Error: Gen Q";
\r
321 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
\r
323 ulTicksToWait = mainERROR_PERIOD;
\r
324 xMessage.pcMessage = "Error: Q Peek";
\r
326 else if( xAreComTestTasksStillRunning() != pdTRUE )
\r
328 ulTicksToWait = mainERROR_PERIOD;
\r
329 xMessage.pcMessage = "Error: COM test";
\r
331 else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
\r
333 ulTicksToWait = mainERROR_PERIOD;
\r
334 xMessage.pcMessage = "Error: Blck time";
\r
336 else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
\r
338 ulTicksToWait = mainERROR_PERIOD;
\r
339 xMessage.pcMessage = "Error: Sem test";
\r
341 else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
\r
343 ulTicksToWait = mainERROR_PERIOD;
\r
344 xMessage.pcMessage = "Error: Int math";
\r
347 /* Write the max jitter time to the string buffer. It will only be
\r
348 displayed if no errors have been detected. */
\r
349 sprintf( cStringBuffer, "%dns max jitter", ( int ) ( ( ulMaxJitter - mainEXPECTED_CLOCKS_BETWEEN_INTERRUPTS ) * mainNS_PER_CLOCK ) );
\r
351 xQueueSend( xLCDQueue, &xMessage, mainDONT_WAIT );
\r
352 vParTestToggleLED( mainCHECK_LED );
\r
355 /*-----------------------------------------------------------*/
\r
357 void vApplicationGeneralExceptionHandler( unsigned portLONG ulCause, unsigned portLONG ulStatus )
\r
359 /* This overrides the definition provided by the kernel. Other exceptions
\r
360 should be handled here. */
\r