]> git.sur5r.net Git - freertos/blob - Demo/Cygnal/main.c
Update to V4.1.0.
[freertos] / Demo / Cygnal / main.c
1 /*\r
2         FreeRTOS.org V4.1.0 - Copyright (C) 2003-2006 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         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
30         ***************************************************************************\r
31 */\r
32 \r
33 /*\r
34  * Creates the demo application tasks, then starts the scheduler.  The WEB\r
35  * documentation provides more details of the demo application tasks.\r
36  * \r
37  * Main. c also creates four other tasks:\r
38  * \r
39  * 1) vErrorChecks()\r
40  * This only executes every few seconds but has the highest priority so is \r
41  * guaranteed to get processor time.  Its main function is to check that all \r
42  * the standard demo application tasks are still operational and have not\r
43  * experienced any errors.  vErrorChecks() will toggle the on board LED\r
44  * every mainNO_ERROR_FLASH_PERIOD milliseconds if none of the demo application\r
45  * tasks have reported an error.  Should any task report an error at any time\r
46  * the rate at which the on board LED is toggled is increased to \r
47  * mainERROR_FLASH_PERIOD - providing visual feedback that something has gone\r
48  * wrong.\r
49  *\r
50  * 2) vRegisterCheck()\r
51  * This is a very simple task that checks that all the registers are always\r
52  * in their expected state.  The task only makes use of the A register, so\r
53  * all the other registers should always contain their initial values.\r
54  * An incorrect value indicates an error in the context switch mechanism.\r
55  * The task operates at the idle priority so will be preempted regularly.\r
56  * Any error will cause the toggle rate of the on board LED to increase to\r
57  * mainERROR_FLASH_PERIOD milliseconds.\r
58  *\r
59  * 3 and 4) vFLOPCheck1() and vFLOPCheck2()\r
60  * These are very basic versions of the standard FLOP tasks.  They are good\r
61  * at detecting errors in the context switch mechanism, and also check that\r
62  * the floating point libraries are correctly built to be re-enterant.  The\r
63  * stack restrictions of the 8051 prevent the use of the standard FLOP demo\r
64  * tasks.\r
65  */\r
66 \r
67 /* Standard includes. */\r
68 #include <stdlib.h>\r
69 \r
70 /* Scheduler includes. */\r
71 #include "FreeRTOS.h"\r
72 #include "task.h"\r
73 \r
74 /* Demo application includes. */\r
75 #include "partest.h"\r
76 #include "flash.h"\r
77 #include "integer.h"\r
78 #include "PollQ.h"\r
79 #include "comtest2.h"\r
80 #include "semtest.h"\r
81 \r
82 /* Demo task priorities. */\r
83 #define mainLED_TASK_PRIORITY           ( tskIDLE_PRIORITY + 1 )\r
84 #define mainQUEUE_POLL_PRIORITY         ( tskIDLE_PRIORITY + 2 )\r
85 #define mainCOM_TEST_PRIORITY           ( tskIDLE_PRIORITY + 2 )\r
86 #define mainCHECK_TASK_PRIORITY         ( tskIDLE_PRIORITY + 3 )\r
87 #define mainSEM_TEST_PRIORITY           ( tskIDLE_PRIORITY + 2 )\r
88 #define mainINTEGER_PRIORITY            tskIDLE_PRIORITY\r
89 \r
90 /* Constants required to disable the watchdog. */\r
91 #define mainDISABLE_BYTE_1                      ( ( unsigned portCHAR ) 0xde )\r
92 #define mainDISABLE_BYTE_2                      ( ( unsigned portCHAR ) 0xad )\r
93 \r
94 /* Constants to setup and use the on board LED. */\r
95 #define ucLED_BIT                                       ( ( unsigned portCHAR ) 0x40 )\r
96 #define mainPORT_1_BIT_6                        ( ( unsigned portCHAR ) 0x40 )\r
97 #define mainENABLE_CROSS_BAR            ( ( unsigned portCHAR ) 0x40 )\r
98 \r
99 /* Constants to set the clock frequency. */\r
100 #define mainSELECT_INTERNAL_OSC         ( ( unsigned portCHAR ) 0x80 )\r
101 #define mainDIVIDE_CLOCK_BY_1           ( ( unsigned portCHAR ) 0x03 )\r
102 #define mainPLL_USES_INTERNAL_OSC       ( ( unsigned portCHAR ) 0x04 )\r
103 #define mainFLASH_READ_TIMING           ( ( unsigned portCHAR ) 0x30 )\r
104 #define mainPLL_POWER_ON                        ( ( unsigned portCHAR ) 0x01 )\r
105 #define mainPLL_NO_PREDIVIDE            ( ( unsigned portCHAR ) 0x01 )\r
106 #define mainPLL_FILTER                          ( ( unsigned portCHAR ) 0x01 )\r
107 #define mainPLL_MULTIPLICATION          ( ( unsigned portCHAR ) 0x04 )\r
108 #define mainENABLE_PLL                          ( ( unsigned portCHAR ) 0x02 )\r
109 #define mainPLL_LOCKED                          ( ( unsigned portCHAR ) 0x10 )\r
110 #define mainSELECT_PLL_AS_SOURCE        ( ( unsigned portCHAR ) 0x02 )\r
111 \r
112 /* Toggle rate for the on board LED - which is dependent on whether or not\r
113 an error has been detected. */\r
114 #define mainNO_ERROR_FLASH_PERIOD       ( ( portTickType ) 5000 )\r
115 #define mainERROR_FLASH_PERIOD          ( ( portTickType ) 250 )\r
116 \r
117 /* Baud rate used by the serial port tasks. */\r
118 #define mainCOM_TEST_BAUD_RATE          ( ( unsigned portLONG ) 115200 )\r
119 \r
120 /* Pass an invalid LED number to the COM test task as we don't want it to flash\r
121 an LED.  There are only 8 LEDs (excluding the on board LED) wired in and these\r
122 are all used by the flash tasks. */\r
123 #define mainCOM_TEST_LED                        ( 200 )\r
124 \r
125 /* We want the Cygnal to act as much as possible as a standard 8052. */\r
126 #define mainAUTO_SFR_OFF                        ( ( unsigned portCHAR ) 0 )\r
127 \r
128 /* Constants required to setup the IO pins for serial comms. */\r
129 #define mainENABLE_COMS                         ( ( unsigned portCHAR ) 0x04 )\r
130 #define mainCOMS_LINES_TO_PUSH_PULL ( ( unsigned portCHAR ) 0x03 )\r
131 \r
132 /* Pointer passed as a parameter to vRegisterCheck() just so it has some know\r
133 values to check for in the DPH, DPL and B registers. */\r
134 #define mainDUMMY_POINTER               ( ( xdata void * ) 0xabcd )\r
135 \r
136 /* Macro that lets vErrorChecks() know that one of the tasks defined in\r
137 main. c has detected an error.  A critical region is used around xLatchError\r
138 as it is accessed from vErrorChecks(), which has a higher priority. */ \r
139 #define mainLATCH_ERROR()                       \\r
140 {                                                                       \\r
141         portENTER_CRITICAL();                   \\r
142                 xLatchedError = pdTRUE;         \\r
143         portEXIT_CRITICAL();                    \\r
144 }\r
145 \r
146 /*\r
147  * Setup the Cygnal microcontroller for its fastest operation. \r
148  */\r
149 static void prvSetupSystemClock( void );\r
150 \r
151 /*\r
152  * Setup the peripherals, including the on board LED. \r
153  */\r
154 static void prvSetupHardware( void );\r
155 \r
156 /*\r
157  * Toggle the state of the on board LED. \r
158  */\r
159 static void prvToggleOnBoardLED( void );\r
160 \r
161 /*\r
162  * See comments at the top of the file for details. \r
163  */\r
164 static void vErrorChecks( void *pvParameters );\r
165 \r
166 /*\r
167  * See comments at the top of the file for details. \r
168  */\r
169 static void vRegisterCheck( void *pvParameters );\r
170 \r
171 /*\r
172  * See comments at the top of the file for details. \r
173  */\r
174 static void vFLOPCheck1( void *pvParameters );\r
175 \r
176 /*\r
177  * See comments at the top of the file for details. \r
178  */\r
179 static void vFLOPCheck2( void *pvParameters );\r
180 \r
181 /* File scope variable used to communicate the occurrence of an error between\r
182 tasks. */\r
183 static portBASE_TYPE xLatchedError = pdFALSE;\r
184 \r
185 /*-----------------------------------------------------------*/\r
186 \r
187 /*\r
188  * Starts all the other tasks, then starts the scheduler. \r
189  */\r
190 void main( void )\r
191 {\r
192         /* Initialise the hardware including the system clock and on board\r
193         LED. */\r
194         prvSetupHardware();\r
195 \r
196         /* Initialise the port that controls the external LED's utilized by the\r
197         flash tasks. */\r
198         vParTestInitialise();\r
199 \r
200         /* Start the used standard demo tasks. */\r
201         vStartLEDFlashTasks( mainLED_TASK_PRIORITY );\r
202         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
203         vStartIntegerMathTasks( mainINTEGER_PRIORITY );\r
204         vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );\r
205         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
206 \r
207         /* Start the tasks defined in this file.  The first three never block so\r
208         must not be used with the co-operative scheduler. */\r
209         #if configUSE_PREEMPTION == 1\r
210         {\r
211                 xTaskCreate( vRegisterCheck, "RegChck", configMINIMAL_STACK_SIZE, mainDUMMY_POINTER, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );\r
212                 xTaskCreate( vFLOPCheck1, "FLOP", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );\r
213                 xTaskCreate( vFLOPCheck2, "FLOP", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL );\r
214         }\r
215         #endif \r
216 \r
217         xTaskCreate( vErrorChecks, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, ( xTaskHandle * ) NULL );\r
218 \r
219         /* Finally kick off the scheduler.  This function should never return. */\r
220         vTaskStartScheduler();\r
221 \r
222         /* Should never reach here as the tasks will now be executing under control\r
223         of the scheduler. */\r
224 }\r
225 /*-----------------------------------------------------------*/\r
226 \r
227 /*\r
228  * Setup the hardware prior to using the scheduler.  Most of the Cygnal\r
229  * specific initialisation is performed here leaving standard 8052 setup\r
230  * only in the driver code.\r
231  */\r
232 static void prvSetupHardware( void )\r
233 {\r
234 unsigned portCHAR ucOriginalSFRPage;\r
235 \r
236         /* Remember the SFR page before it is changed so it can get set back\r
237         before the function exits. */\r
238         ucOriginalSFRPage = SFRPAGE;\r
239 \r
240         /* Setup the SFR page to access the config SFR's. */\r
241         SFRPAGE = CONFIG_PAGE;\r
242 \r
243         /* Don't allow the microcontroller to automatically switch SFR page, as the\r
244         SFR page is not stored as part of the task context. */\r
245         SFRPGCN = mainAUTO_SFR_OFF;\r
246 \r
247         /* Disable the watchdog. */\r
248         WDTCN = mainDISABLE_BYTE_1;\r
249         WDTCN = mainDISABLE_BYTE_2;\r
250 \r
251         /* Set the on board LED to push pull. */\r
252         P1MDOUT |= mainPORT_1_BIT_6;\r
253 \r
254         /* Setup the cross bar to enable serial comms here as it is not part of the \r
255         standard 8051 setup and therefore is not in the driver code. */\r
256         XBR0 |= mainENABLE_COMS;\r
257         P0MDOUT |= mainCOMS_LINES_TO_PUSH_PULL;\r
258 \r
259         /* Enable the cross bar so our hardware setup takes effect. */\r
260         XBR2 = mainENABLE_CROSS_BAR;\r
261 \r
262         /* Setup a fast system clock. */\r
263         prvSetupSystemClock();\r
264 \r
265         /* Return the SFR page. */\r
266         SFRPAGE = ucOriginalSFRPage;\r
267 }\r
268 /*-----------------------------------------------------------*/\r
269 \r
270 static void prvSetupSystemClock( void )\r
271 {\r
272 volatile unsigned portSHORT usWait;\r
273 const unsigned portSHORT usWaitTime = ( unsigned portSHORT ) 0x2ff;\r
274 unsigned portCHAR ucOriginalSFRPage;\r
275 \r
276         /* Remember the SFR page so we can set it back at the end. */\r
277         ucOriginalSFRPage = SFRPAGE;\r
278         SFRPAGE = CONFIG_PAGE;\r
279 \r
280         /* Use the internal oscillator set to its fasted frequency. */\r
281         OSCICN = mainSELECT_INTERNAL_OSC | mainDIVIDE_CLOCK_BY_1;\r
282 \r
283         /* Ensure the clock is stable. */\r
284         for( usWait = 0; usWait < usWaitTime; usWait++ );\r
285 \r
286         /* Setup the clock source for the PLL. */\r
287         PLL0CN &= ~mainPLL_USES_INTERNAL_OSC;\r
288 \r
289         /* Change the read timing for the flash ready for the fast clock. */\r
290         SFRPAGE = LEGACY_PAGE;\r
291         FLSCL |= mainFLASH_READ_TIMING;\r
292 \r
293         /* Turn on the PLL power. */\r
294         SFRPAGE = CONFIG_PAGE;\r
295         PLL0CN |= mainPLL_POWER_ON;\r
296 \r
297         /* Don't predivide the clock. */\r
298         PLL0DIV = mainPLL_NO_PREDIVIDE;\r
299 \r
300         /* Set filter for fastest clock. */\r
301         PLL0FLT = mainPLL_FILTER;\r
302         PLL0MUL = mainPLL_MULTIPLICATION;\r
303 \r
304         /* Ensure the clock is stable. */\r
305         for( usWait = 0; usWait < usWaitTime; usWait++ );\r
306 \r
307         /* Enable the PLL and wait for it to lock. */\r
308         PLL0CN |= mainENABLE_PLL;\r
309         for( usWait = 0; usWait < usWaitTime; usWait++ )\r
310         {\r
311                 if( PLL0CN & mainPLL_LOCKED )\r
312                 {\r
313                         break;\r
314                 }\r
315         }\r
316 \r
317         /* Select the PLL as the clock source. */\r
318         CLKSEL |= mainSELECT_PLL_AS_SOURCE;\r
319 \r
320         /* Return the SFR back to its original value. */\r
321         SFRPAGE = ucOriginalSFRPage;\r
322 }\r
323 /*-----------------------------------------------------------*/\r
324 \r
325 static void prvToggleOnBoardLED( void )\r
326 {\r
327         /* If the on board LED is on, turn it off and visa versa. */\r
328         if( P1 & ucLED_BIT )\r
329         {\r
330                 P1 &= ~ucLED_BIT;\r
331         }\r
332         else\r
333         {\r
334                 P1 |= ucLED_BIT;\r
335         }\r
336 }\r
337 /*-----------------------------------------------------------*/\r
338 \r
339 /*\r
340  * See the documentation at the top of this file. \r
341  */\r
342 static void vErrorChecks( void *pvParameters )\r
343 {\r
344 portBASE_TYPE xErrorHasOccurred = pdFALSE;\r
345         \r
346         /* Just to prevent compiler warnings. */\r
347         ( void ) pvParameters;\r
348         \r
349         /* Cycle for ever, delaying then checking all the other tasks are still\r
350         operating without error.   The delay period depends on whether an error\r
351         has ever been detected. */\r
352         for( ;; )\r
353         {\r
354                 if( xLatchedError == pdFALSE )\r
355                 {               \r
356                         /* No errors have been detected so delay for a longer period.  The\r
357                         on board LED will get toggled every mainNO_ERROR_FLASH_PERIOD ms. */\r
358                         vTaskDelay( mainNO_ERROR_FLASH_PERIOD );\r
359                 }\r
360                 else\r
361                 {\r
362                         /* We have at some time recognised an error in one of the demo\r
363                         application tasks, delay for a shorter period.  The on board LED\r
364                         will get toggled every mainERROR_FLASH_PERIOD ms. */\r
365                         vTaskDelay( mainERROR_FLASH_PERIOD );\r
366                 }\r
367 \r
368                 \r
369                 \r
370                 /* Check the demo application tasks for errors. */\r
371 \r
372                 if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
373                 {\r
374                         xErrorHasOccurred = pdTRUE;\r
375                 }\r
376 \r
377                 if( xArePollingQueuesStillRunning() != pdTRUE )\r
378                 {\r
379                         xErrorHasOccurred = pdTRUE;\r
380                 }\r
381 \r
382                 if( xAreComTestTasksStillRunning() != pdTRUE )\r
383                 {\r
384                         xErrorHasOccurred = pdTRUE;\r
385                 }\r
386 \r
387                 if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
388                 {\r
389                         xErrorHasOccurred = pdTRUE;\r
390                 }\r
391 \r
392                 /* If an error has occurred, latch it to cause the LED flash rate to \r
393                 increase. */\r
394                 if( xErrorHasOccurred == pdTRUE )\r
395                 {\r
396                         xLatchedError = pdTRUE;\r
397                 }\r
398 \r
399                 /* Toggle the LED to indicate the completion of a check cycle.  The\r
400                 frequency of check cycles is dependent on whether or not we have \r
401                 latched an error. */\r
402                 prvToggleOnBoardLED();\r
403         }\r
404 }\r
405 /*-----------------------------------------------------------*/\r
406 \r
407 /*\r
408  * See the documentation at the top of this file.  Also see the standard FLOP\r
409  * demo task documentation for the rationale of these tasks.\r
410  */\r
411 static void vFLOPCheck1( void *pvParameters )\r
412 {\r
413 volatile portFLOAT fVal1, fVal2, fResult;\r
414 \r
415         ( void ) pvParameters;\r
416 \r
417         for( ;; )\r
418         {\r
419                 fVal1 = ( portFLOAT ) -1234.5678;\r
420                 fVal2 = ( portFLOAT ) 2345.6789;\r
421 \r
422                 fResult = fVal1 + fVal2;\r
423                 if( ( fResult > ( portFLOAT )  1111.15 ) || ( fResult < ( portFLOAT ) 1111.05 ) )\r
424                 {\r
425                         mainLATCH_ERROR();\r
426                 }\r
427 \r
428                 fResult = fVal1 / fVal2;\r
429                 if( ( fResult > ( portFLOAT ) -0.51 ) || ( fResult < ( portFLOAT ) -0.53 ) )\r
430                 {\r
431                         mainLATCH_ERROR();\r
432                 }\r
433         }\r
434 }\r
435 /*-----------------------------------------------------------*/\r
436 \r
437 /*\r
438  * See the documentation at the top of this file.\r
439  */\r
440 static void vFLOPCheck2( void *pvParameters )\r
441 {\r
442 volatile portFLOAT fVal1, fVal2, fResult;\r
443 \r
444         ( void ) pvParameters;\r
445 \r
446         for( ;; )\r
447         {\r
448                 fVal1 = ( portFLOAT ) -12340.5678;\r
449                 fVal2 = ( portFLOAT ) 23450.6789;\r
450 \r
451                 fResult = fVal1 + fVal2;\r
452                 if( ( fResult > ( portFLOAT ) 11110.15 ) || ( fResult < ( portFLOAT ) 11110.05 ) )\r
453                 {\r
454                         mainLATCH_ERROR();\r
455                 }\r
456 \r
457                 fResult = fVal1 / -fVal2;\r
458                 if( ( fResult > ( portFLOAT ) 0.53 ) || ( fResult < ( portFLOAT ) 0.51 ) )\r
459                 {\r
460                         mainLATCH_ERROR();\r
461                 }\r
462         }\r
463 }\r
464 /*-----------------------------------------------------------*/\r
465 \r
466 /*\r
467  * See the documentation at the top of this file. \r
468  */\r
469 static void vRegisterCheck( void *pvParameters )\r
470 {\r
471         ( void ) pvParameters;\r
472 \r
473         for( ;; )\r
474         {\r
475                 if( SP != configSTACK_START )\r
476                 {\r
477                         mainLATCH_ERROR();\r
478                 }\r
479 \r
480                 _asm\r
481                         MOV ACC, ar0\r
482                 _endasm;\r
483 \r
484                 if( ACC != 0 )\r
485                 {\r
486                         mainLATCH_ERROR();\r
487                 }\r
488 \r
489                 _asm\r
490                         MOV ACC, ar1\r
491                 _endasm;\r
492 \r
493                 if( ACC != 1 )\r
494                 {\r
495                         mainLATCH_ERROR();\r
496                 }\r
497                 _asm\r
498                         MOV ACC, ar2\r
499                 _endasm;\r
500 \r
501                 if( ACC != 2 )\r
502                 {\r
503                         mainLATCH_ERROR();\r
504                 }\r
505                 _asm\r
506                         MOV ACC, ar3\r
507                 _endasm;\r
508 \r
509                 if( ACC != 3 )\r
510                 {\r
511                         mainLATCH_ERROR();\r
512                 }\r
513                 _asm\r
514                         MOV ACC, ar4\r
515                 _endasm;\r
516 \r
517                 if( ACC != 4 )\r
518                 {\r
519                         mainLATCH_ERROR();\r
520                 }\r
521                 _asm\r
522                         MOV ACC, ar5\r
523                 _endasm;\r
524 \r
525                 if( ACC != 5 )\r
526                 {\r
527                         mainLATCH_ERROR();\r
528                 }\r
529                 _asm\r
530                         MOV ACC, ar6\r
531                 _endasm;\r
532 \r
533                 if( ACC != 6 )\r
534                 {\r
535                         mainLATCH_ERROR();\r
536                 }\r
537                 _asm\r
538                         MOV ACC, ar7\r
539                 _endasm;\r
540 \r
541                 if( ACC != 7 )\r
542                 {\r
543                         mainLATCH_ERROR();\r
544                 }\r
545 \r
546                 if( DPL != 0xcd )\r
547                 {\r
548                         mainLATCH_ERROR();\r
549                 }\r
550 \r
551                 if( DPH != 0xab )\r
552                 {\r
553                         mainLATCH_ERROR();\r
554                 }\r
555 \r
556                 if( B != 0x01 )\r
557                 {\r
558                         mainLATCH_ERROR();\r
559                 }                       \r
560         }\r
561 }\r
562 \r
563 \r