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