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