]> git.sur5r.net Git - freertos/blob - Demo/PIC32MX_MPLAB/main.c
12e9912f1fafdde6c56cf1c631362d83defa5e82
[freertos] / Demo / PIC32MX_MPLAB / main.c
1 /*\r
2         FreeRTOS.org V5.0.0 - Copyright (C) 2003-2008 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \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
10 \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
15 \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
19 \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
24         can be applied.\r
25 \r
26     ***************************************************************************\r
27     ***************************************************************************\r
28     *                                                                         *\r
29     * SAVE TIME AND MONEY!  We can port FreeRTOS.org to your own hardware,    *\r
30     * and even write all or part of your application on your behalf.          *\r
31     * See http://www.OpenRTOS.com for details of the services we provide to   *\r
32     * expedite your project.                                                  *\r
33     *                                                                         *\r
34     ***************************************************************************\r
35     ***************************************************************************\r
36 \r
37         Please ensure to read the configuration and relevant port sections of the\r
38         online documentation.\r
39 \r
40         http://www.FreeRTOS.org - Documentation, latest information, license and \r
41         contact details.\r
42 \r
43         http://www.SafeRTOS.com - A version that is certified for use in safety \r
44         critical systems.\r
45 \r
46         http://www.OpenRTOS.com - Commercial support, development, porting, \r
47         licensing and training services.\r
48 */\r
49 \r
50 /*\r
51  * Creates all the demo application tasks, then starts the scheduler.  The WEB\r
52  * documentation provides more details of the standard demo application tasks.\r
53  * In addition to the standard demo tasks, the following tasks and tests are\r
54  * defined and/or created within this file:\r
55  *\r
56  * "Fast Interrupt Test" - A high frequency periodic interrupt is generated\r
57  * using a free running timer to demonstrate the use of the\r
58  * configKERNEL_INTERRUPT_PRIORITY configuration constant.  The interrupt\r
59  * service routine measures the number of processor clocks that occur between\r
60  * each interrupt - and in so doing measures the jitter in the interrupt timing.\r
61  * The maximum measured jitter time is latched in the ulMaxJitter variable, and\r
62  * displayed on the LCD display by the 'LCD' task as described below.  The\r
63  * fast interrupt is configured and handled in the timertest.c source file.\r
64  *\r
65  * "LCD" task - the LCD task is a 'gatekeeper' task.  It is the only task that\r
66  * is permitted to access the display directly.  Other tasks wishing to write a\r
67  * message to the LCD send the message on a queue to the LCD task instead of\r
68  * accessing the LCD themselves.  The LCD task just blocks on the queue waiting\r
69  * for messages - waking and displaying the messages as they arrive.\r
70  *\r
71  * "Check" task -  This only executes every three seconds but has the highest\r
72  * priority so is guaranteed to get processor time.  Its main function is to \r
73  * check that all the standard demo tasks are still operational.  Should any \r
74  * unexpected behaviour within a demo task be discovered the check task will \r
75  * write an error to the LCD (via the LCD task).  If all the demo tasks are \r
76  * executing with their expected behaviour then the check task writes the \r
77  * maximum jitter time to the LCD (as described above) - again via the LCD task.\r
78  *\r
79  * "Register test" tasks - These tasks are used in part to test the kernel port.\r
80  * They set each processor register to a known value, then check that the \r
81  * register still contains that value.  Each of the tasks sets the registers\r
82  * to different values, and will get swapping in and out between setting and \r
83  * then subsequently checking the register values.  Discovery of an incorrect\r
84  * value would be indicative of an error in the task switching mechanism.\r
85  */\r
86 \r
87 /* Standard includes. */\r
88 #include <stdio.h>\r
89 \r
90 /* Scheduler includes. */\r
91 #include "FreeRTOS.h"\r
92 #include "task.h"\r
93 #include "queue.h"\r
94 \r
95 /* Demo application includes. */\r
96 #include "partest.h"\r
97 #include "integer.h"\r
98 #include "blocktim.h"\r
99 #include "flash.h"\r
100 #include "semtest.h"\r
101 #include "GenQTest.h"\r
102 #include "QPeek.h"\r
103 #include "lcd.h"\r
104 #include "comtest2.h"\r
105 #include "timertest.h"\r
106 \r
107 #pragma config FPLLMUL = MUL_18, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF\r
108 #pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_2\r
109 \r
110 /*-----------------------------------------------------------*/\r
111 \r
112 /* The rate at which the LED controlled by the 'check' task will flash when no\r
113 errors have been detected. */\r
114 #define mainNO_ERROR_PERIOD     ( 3000 / portTICK_RATE_MS )\r
115 \r
116 /* The rate at which the LED controlled by the 'check' task will flash when an\r
117 error has been detected. */\r
118 #define mainERROR_PERIOD        ( 500 )\r
119 \r
120 /* The priorities of the various demo application tasks. */\r
121 #define mainCHECK_TASK_PRIORITY                         ( tskIDLE_PRIORITY + 4 )\r
122 #define mainSEM_TEST_PRIORITY                           ( tskIDLE_PRIORITY + 1 )\r
123 #define mainBLOCK_Q_PRIORITY                            ( tskIDLE_PRIORITY + 2 )\r
124 #define mainCOM_TEST_PRIORITY                           ( tskIDLE_PRIORITY + 2 )\r
125 #define mainINTEGER_TASK_PRIORITY           ( tskIDLE_PRIORITY )\r
126 #define mainGEN_QUEUE_TASK_PRIORITY                     ( tskIDLE_PRIORITY )\r
127 \r
128 /* The LED controlled by the 'check' task. */\r
129 #define mainCHECK_LED                                           ( 7 )\r
130 \r
131 /* The LED used by the comtest tasks.  mainCOM_TEST_LED + 1 is also used.\r
132 See the comtest.c file for more information. */\r
133 #define mainCOM_TEST_LED                                        ( 4 )\r
134 \r
135 /* Baud rate used by the comtest tasks. */\r
136 #define mainCOM_TEST_BAUD_RATE                          ( 115200 )\r
137 \r
138 /* Misc. */\r
139 #define mainDONT_WAIT                                           ( 0 )\r
140 \r
141 /* Dimension the buffer used to hold the value of the maximum jitter time when\r
142 it is converted to a string. */\r
143 #define mainMAX_STRING_LENGTH                           ( 20 )\r
144 \r
145 /* The frequency at which the "fast interrupt test" interrupt will occur. */\r
146 #define mainTEST_INTERRUPT_FREQUENCY            ( 20000 )\r
147 \r
148 /* The number of timer clocks we expect to occur between each "fast\r
149 interrupt test" interrupt. */\r
150 #define mainEXPECTED_CLOCKS_BETWEEN_INTERRUPTS ( ( configCPU_CLOCK_HZ >> 1 ) / mainTEST_INTERRUPT_FREQUENCY )\r
151 \r
152 /* The number of nano seconds between each core clock. */\r
153 #define mainNS_PER_CLOCK ( ( unsigned portLONG ) ( ( 1.0 / ( double ) ( configCPU_CLOCK_HZ >> 1 ) ) * 1000000000.0 ) )\r
154 \r
155 /*-----------------------------------------------------------*/\r
156 \r
157 /*\r
158  * Setup the processor ready for the demo.\r
159  */\r
160 static void prvSetupHardware( void );\r
161 \r
162 /*\r
163  * Implements the 'check' task functionality as described at the top of this \r
164  * file. \r
165  */\r
166 static void prvCheckTask( void *pvParameters ) __attribute__((noreturn));\r
167 \r
168 /*\r
169  * Tasks that test the context switch mechanism by filling the processor \r
170  * registers with known values, then checking that the values contained\r
171  * within the registers is as expected.  The tasks are likely to get swapped\r
172  * in and out between setting the register values and checking the register\r
173  * values. */\r
174 static void prvTestTask1( void *pvParameters );\r
175 static void prvTestTask2( void *pvParameters );\r
176 \r
177 /*-----------------------------------------------------------*/\r
178 \r
179 /* The queue used to send messages to the LCD task. */\r
180 static xQueueHandle xLCDQueue;\r
181 \r
182 /* Flag used by prvTestTask1() and prvTestTask2() to indicate their status\r
183 (pass/fail). */\r
184 unsigned portLONG ulStatus1 = pdPASS;\r
185 \r
186 /* Variables incremented by prvTestTask1() and prvTestTask2() respectively on \r
187 each iteration of their function.  This is used to detect either task stopping\r
188 their execution.. */\r
189 unsigned portLONG ulRegTest1Cycles = 0, ulRegTest2Cycles = 0;\r
190 \r
191 /*-----------------------------------------------------------*/\r
192 \r
193 /*\r
194  * Create the demo tasks then start the scheduler.\r
195  */\r
196 int main( void )\r
197 {\r
198         /* Configure any hardware required for this demo. */\r
199         prvSetupHardware();\r
200 \r
201         /* Create the LCD task - this returns the queue to use when writing \r
202         messages to the LCD. */\r
203         xLCDQueue = xStartLCDTask();\r
204 \r
205         /* Create all the other standard demo tasks. */\r
206         vStartLEDFlashTasks( tskIDLE_PRIORITY );\r
207     vCreateBlockTimeTasks();\r
208     vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
209     vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );\r
210     vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );\r
211     vStartQueuePeekTasks();\r
212         vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );\r
213 \r
214         /* Create the tasks defined within this file. */\r
215         xTaskCreate( prvTestTask1, "Tst1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
216         xTaskCreate( prvTestTask2, "Tst2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
217 \r
218         /* prvCheckTask uses sprintf so requires more stack. */\r
219         xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE * 2, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
220 \r
221         /* Finally start the scheduler. */\r
222         vTaskStartScheduler();\r
223 \r
224         /* Will only reach here if there is insufficient heap available to start\r
225         the scheduler. */\r
226         return 0;\r
227 }\r
228 /*-----------------------------------------------------------*/\r
229 \r
230 static void prvTestTask1( void *pvParameters )\r
231 {\r
232 extern void vRegTest1( unsigned long * );\r
233 \r
234         for( ;; )\r
235         {\r
236                 /* Perform the register test function. */\r
237                 vRegTest1( &ulStatus1 );\r
238 \r
239                 /* Increment the counter so the check task knows we are still \r
240                 running. */\r
241                 ulRegTest1Cycles++;\r
242         }\r
243 }\r
244 /*-----------------------------------------------------------*/\r
245 \r
246 static void prvTestTask2( void *pvParameters )\r
247 {\r
248 extern void vRegTest2( unsigned long * );\r
249 \r
250         for( ;; )\r
251         {\r
252                 /* Perform the register test function. */\r
253                 vRegTest2( &ulStatus1 );\r
254 \r
255                 /* Increment the counter so the check task knows we are still\r
256                 running. */\r
257                 ulRegTest2Cycles++;\r
258         }\r
259 }\r
260 /*-----------------------------------------------------------*/\r
261 \r
262 static void prvSetupHardware( void )\r
263 {\r
264         /* Set the system and peripheral bus speeds and enable the program cache*/\r
265     SYSTEMConfigPerformance( configCPU_CLOCK_HZ );\r
266 \r
267         /* Setup to use the external interrupt controller. */\r
268     INTEnableSystemMultiVectoredInt();\r
269 \r
270         portDISABLE_INTERRUPTS();\r
271 \r
272         /* Setup the digital IO for the LED's. */\r
273         vParTestInitialise();\r
274 }\r
275 /*-----------------------------------------------------------*/\r
276 \r
277 static void prvCheckTask( void *pvParameters )\r
278 {\r
279 unsigned portLONG ulLastRegTest1Value = 0, ulLastRegTest2Value = 0, ulTicksToWait = mainNO_ERROR_PERIOD;\r
280 portTickType xLastExecutionTime;\r
281 \r
282 /* Buffer into which the maximum jitter time is written as a string. */\r
283 static portCHAR cStringBuffer[ mainMAX_STRING_LENGTH ];\r
284 \r
285 /* The maximum jitter time measured by the fast interrupt test. */\r
286 extern unsigned portLONG ulMaxJitter ;\r
287 xLCDMessage xMessage = { ( 200 / portTICK_RATE_MS ), cStringBuffer };\r
288 \r
289         /* Setup the high frequency, high priority, timer test.  It is setup here\r
290         to ensure it does not fire before the scheduler is started. */\r
291         vSetupTimerTest( mainTEST_INTERRUPT_FREQUENCY );\r
292 \r
293         /* Initialise the variable used to control our iteration rate prior to\r
294         its first use. */\r
295         xLastExecutionTime = xTaskGetTickCount();\r
296 \r
297         for( ;; )\r
298         {\r
299                 /* Wait until it is time to run the tests again. */\r
300                 vTaskDelayUntil( &xLastExecutionTime, ulTicksToWait );\r
301 \r
302                 /* Has either register check 1 or 2 task discovered an error? */\r
303                 if( ulStatus1 != pdPASS )\r
304                 {\r
305                         ulTicksToWait = mainERROR_PERIOD;\r
306                         xMessage.pcMessage = "Error: Reg test1";\r
307                 }\r
308 \r
309                 /* Check that the register test 1 task is still running. */\r
310                 if( ulLastRegTest1Value == ulRegTest1Cycles )\r
311                 {\r
312                         ulTicksToWait = mainERROR_PERIOD;\r
313                         xMessage.pcMessage = "Error: Reg test2";\r
314                 }\r
315                 ulLastRegTest1Value = ulRegTest1Cycles;\r
316 \r
317                 \r
318                 /* Check that the register test 2 task is still running. */\r
319                 if( ulLastRegTest2Value == ulRegTest2Cycles )\r
320                 {\r
321                         ulTicksToWait = mainERROR_PERIOD;\r
322                         xMessage.pcMessage = "Error: Reg test3";\r
323                 }\r
324                 ulLastRegTest2Value = ulRegTest2Cycles;\r
325                 \r
326 \r
327                 /* Have any of the standard demo tasks detected an error in their \r
328                 operation? */\r
329                 if( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
330                 {\r
331                         ulTicksToWait = mainERROR_PERIOD;\r
332                         xMessage.pcMessage = "Error: Gen Q";\r
333                 }\r
334                 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
335                 {\r
336                         ulTicksToWait = mainERROR_PERIOD;\r
337                         xMessage.pcMessage = "Error: Q Peek";\r
338                 }\r
339                 else if( xAreComTestTasksStillRunning() != pdTRUE )\r
340                 {\r
341                         ulTicksToWait = mainERROR_PERIOD;\r
342                         xMessage.pcMessage = "Error: COM test";\r
343                 }\r
344                 else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )\r
345                 {\r
346                         ulTicksToWait = mainERROR_PERIOD;\r
347                         xMessage.pcMessage = "Error: Blck time";\r
348                 }\r
349             else if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
350             {\r
351                 ulTicksToWait = mainERROR_PERIOD;\r
352                         xMessage.pcMessage = "Error: Sem test";\r
353             }\r
354             else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
355             {\r
356                 ulTicksToWait = mainERROR_PERIOD;\r
357                         xMessage.pcMessage = "Error: Int math";\r
358             }\r
359 \r
360                 /* Write the max jitter time to the string buffer.  It will only be \r
361                 displayed if no errors have been detected. */\r
362                 sprintf( cStringBuffer, "%dns max jitter", ( int ) ( ( ulMaxJitter - mainEXPECTED_CLOCKS_BETWEEN_INTERRUPTS ) * mainNS_PER_CLOCK ) );\r
363 \r
364                 xQueueSend( xLCDQueue, &xMessage, mainDONT_WAIT );\r
365                 vParTestToggleLED( mainCHECK_LED );\r
366         }\r
367 }\r
368 /*-----------------------------------------------------------*/\r
369 \r
370 void vApplicationStackOverflowHook( void )\r
371 {\r
372         for( ;; );\r
373 }\r
374 /*-----------------------------------------------------------*/\r
375 \r
376 void _general_exception_handler( unsigned portLONG ulCause, unsigned portLONG ulStatus )\r
377 {\r
378         /* This overrides the definition provided by the kernel.  Other exceptions \r
379         should be handled here. */\r
380         for( ;; );\r
381 }\r