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