]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_AT91SAM3U256_IAR/main.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Demo / CORTEX_AT91SAM3U256_IAR / main.c
1 /*\r
2  * FreeRTOS Kernel V10.3.0\r
3  * Copyright (C) 2020 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 all the demo application tasks, then starts the scheduler.  The WEB\r
30  * documentation provides more details of the standard demo application tasks\r
31  * (which just exist to test the kernel port and provide an example of how to use\r
32  * each FreeRTOS API function).\r
33  *\r
34  * In addition to the standard demo tasks, the following tasks and tests are\r
35  * defined and/or created within this file:\r
36  *\r
37  * "LCD" task - the LCD task is a 'gatekeeper' task.  It is the only task that\r
38  * is permitted to access the display directly.  Other tasks wishing to write a\r
39  * message to the LCD send the message on a queue to the LCD task instead of\r
40  * accessing the LCD themselves.  The LCD task just blocks on the queue waiting\r
41  * for messages - waking and displaying the messages as they arrive.  The use\r
42  * of a gatekeeper in this manner permits both tasks and interrupts to write to\r
43  * the LCD without worrying about mutual exclusion.  This is demonstrated by the\r
44  * check hook (see below) which sends messages to the display even though it\r
45  * executes from an interrupt context.\r
46  *\r
47  * "Check" hook -  This only executes fully every five seconds from the tick\r
48  * hook.  Its main function is to check that all the standard demo tasks are\r
49  * still operational.  Should any unexpected behaviour be discovered within a\r
50  * demo task then the tick hook will write an error to the LCD (via the LCD task).\r
51  * If all the demo tasks are executing with their expected behaviour then the\r
52  * check task writes PASS to the LCD (again via the LCD task), as described above.\r
53  *\r
54  */\r
55 \r
56 /* Scheduler includes. */\r
57 #include "FreeRTOS.h"\r
58 #include "task.h"\r
59 #include "queue.h"\r
60 #include "semphr.h"\r
61 \r
62 /* Demo app includes. */\r
63 #include "BlockQ.h"\r
64 #include "integer.h"\r
65 #include "blocktim.h"\r
66 #include "flash.h"\r
67 #include "partest.h"\r
68 #include "semtest.h"\r
69 #include "PollQ.h"\r
70 #include "lcd_message.h"\r
71 #include "GenQTest.h"\r
72 #include "QPeek.h"\r
73 #include "recmutex.h"\r
74 #include "flash.h"\r
75 #include "comtest2.h"\r
76 \r
77 /* Atmel library includes. */\r
78 #include <board.h>\r
79 #include <lcd/color.h>\r
80 #include <lcd/lcdd.h>\r
81 #include <lcd/draw.h>\r
82 \r
83 \r
84 /*-----------------------------------------------------------*/\r
85 \r
86 /* The time between cycles of the 'check' functionality (defined within the\r
87 tick hook). */\r
88 #define mainCHECK_DELAY                                         ( ( TickType_t ) 5000 / portTICK_PERIOD_MS )\r
89 \r
90 /* The LCD task uses the sprintf function so requires a little more stack too. */\r
91 #define mainLCD_TASK_STACK_SIZE                         ( configMINIMAL_STACK_SIZE * 2 )\r
92 \r
93 /* Task priorities. */\r
94 #define mainQUEUE_POLL_PRIORITY                         ( tskIDLE_PRIORITY + 2 )\r
95 #define mainSEM_TEST_PRIORITY                           ( tskIDLE_PRIORITY + 1 )\r
96 #define mainBLOCK_Q_PRIORITY                            ( tskIDLE_PRIORITY + 2 )\r
97 #define mainLED_TASK_PRIORITY                           ( tskIDLE_PRIORITY + 1 )\r
98 #define mainCOM_TEST_PRIORITY                           ( tskIDLE_PRIORITY + 2 )\r
99 #define mainINTEGER_TASK_PRIORITY           ( tskIDLE_PRIORITY )\r
100 #define mainGEN_QUEUE_TASK_PRIORITY                     ( tskIDLE_PRIORITY )\r
101 \r
102 /* The maximum number of message that can be waiting for display at any one\r
103 time. */\r
104 #define mainLCD_QUEUE_SIZE                                      ( 3 )\r
105 \r
106 /* Constants used by the comtest tasks.  There isn't a spare LED so an invalid\r
107 LED is specified. */\r
108 #define mainBAUD_RATE                                           ( 115200 )\r
109 #define mainCOM_TEST_LED                                        ( 10 )\r
110 \r
111 /*-----------------------------------------------------------*/\r
112 \r
113 /*\r
114  * Configure the hardware for the demo.\r
115  */\r
116 static void prvSetupHardware( void );\r
117 \r
118 /*\r
119  * The LCD gatekeeper task.  Tasks wishing to write to the LCD do not access\r
120  * the LCD directly, but instead send the message to the LCD gatekeeper task.\r
121  */\r
122 static void prvLCDTask( void *pvParameters );\r
123 \r
124 /*\r
125  * Hook functions that can get called by the kernel.  The 'check' functionality\r
126  * is implemented within the tick hook.\r
127  */\r
128 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );\r
129 \r
130 /*\r
131  * The tick hook function as described in the comments at the top of this file.\r
132  * The tick hook is used to monitor all the standard demo tasks to look for\r
133  * errors.  The tick hook is also used to demonstrate how the LCD gatekeeper\r
134  * task can be used to allow interrupts to write to the LCD.\r
135  */\r
136 void vApplicationTickHook( void );\r
137 \r
138 \r
139 /*-----------------------------------------------------------*/\r
140 \r
141 /* The queue used to send messages to the LCD task. */\r
142 static QueueHandle_t xLCDQueue;\r
143 \r
144 /*-----------------------------------------------------------*/\r
145 \r
146 int main( void )\r
147 {\r
148         /* Prepare the hardware. */\r
149         prvSetupHardware();\r
150 \r
151         /* Create the queue used by the LCD task.  Messages for display on the LCD\r
152         are received via this queue. */\r
153         xLCDQueue = xQueueCreate( mainLCD_QUEUE_SIZE, sizeof( xLCDMessage ) );\r
154 \r
155         /* Start the standard demo tasks.  These do nothing other than test the\r
156         port and provide some APU usage examples. */\r
157     vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );\r
158     vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );\r
159         vStartRecursiveMutexTasks();\r
160         vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
161         vCreateBlockTimeTasks();\r
162         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
163         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
164         vStartQueuePeekTasks();\r
165         vStartLEDFlashTasks( mainLED_TASK_PRIORITY );\r
166         vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainBAUD_RATE, mainCOM_TEST_LED );\r
167 \r
168         /* Start the tasks defined within this file/specific to this demo. */\r
169         xTaskCreate( prvLCDTask, "LCD", mainLCD_TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
170 \r
171         /* Start the scheduler. */\r
172         vTaskStartScheduler();\r
173 \r
174     /* Will only get here if there was insufficient memory to create the idle\r
175     task. */\r
176         return 0;\r
177 }\r
178 /*-----------------------------------------------------------*/\r
179 \r
180 void prvSetupHardware( void )\r
181 {\r
182         /* Initialise the port used for the LED outputs. */\r
183         vParTestInitialise();\r
184 }\r
185 /*-----------------------------------------------------------*/\r
186 \r
187 void vApplicationTickHook( void )\r
188 {\r
189 static xLCDMessage xMessage = { "PASS" };\r
190 static unsigned long ulTicksSinceLastDisplay = 0;\r
191 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
192 \r
193         /* Called from every tick interrupt.  Have enough ticks passed to make it\r
194         time to perform our health status check again? */\r
195         ulTicksSinceLastDisplay++;\r
196         if( ulTicksSinceLastDisplay >= mainCHECK_DELAY )\r
197         {\r
198                 ulTicksSinceLastDisplay = 0;\r
199 \r
200                 /* Has an error been found in any task? */\r
201                 if( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
202                 {\r
203                         xMessage.pcMessage = "ERROR IN GEN Q";\r
204                 }\r
205             if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
206             {\r
207                 xMessage.pcMessage = "ERROR IN MATH";\r
208             }\r
209                 else if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
210                 {\r
211                         xMessage.pcMessage = "ERROR IN BLOCK Q";\r
212                 }\r
213                 else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )\r
214                 {\r
215                         xMessage.pcMessage = "ERROR IN BLOCK TIME";\r
216                 }\r
217                 else if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
218                 {\r
219                         xMessage.pcMessage = "ERROR IN SEMAPHORE";\r
220                 }\r
221                 else if( xArePollingQueuesStillRunning() != pdTRUE )\r
222                 {\r
223                         xMessage.pcMessage = "ERROR IN POLL Q";\r
224                 }\r
225                 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
226                 {\r
227                         xMessage.pcMessage = "ERROR IN PEEK Q";\r
228                 }\r
229                 else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
230                 {\r
231                         xMessage.pcMessage = "ERROR IN REC MUTEX";\r
232                 }\r
233                 else if( xAreComTestTasksStillRunning() != pdTRUE )\r
234                 {\r
235                         xMessage.pcMessage = "ERROR IN COMTEST";\r
236                 }\r
237 \r
238                 /* Send the message to the LCD gatekeeper for display. */\r
239                 xHigherPriorityTaskWoken = pdFALSE;\r
240                 xQueueSendFromISR( xLCDQueue, &xMessage, &xHigherPriorityTaskWoken );\r
241         }\r
242 }\r
243 /*-----------------------------------------------------------*/\r
244 \r
245 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )\r
246 {\r
247         ( void ) pxTask;\r
248         ( void ) pcTaskName;\r
249 \r
250         /* If the parameters have been corrupted then inspect pxCurrentTCB to\r
251         identify which task has overflowed its stack. */\r
252         for( ;; );\r
253 }\r
254 /*-----------------------------------------------------------*/\r
255 \r
256 static void prvLCDTask( void *pvParameters )\r
257 {\r
258 xLCDMessage xMessage;\r
259 unsigned long ulY = 0;\r
260 const unsigned long ulX = 5;\r
261 const unsigned long ulMaxY = 250, ulYIncrement = 22, ulWidth = 250, ulHeight = 20;;\r
262 \r
263     /* Initialize LCD. */\r
264     LCDD_Initialize();\r
265     LCDD_Start();\r
266         LCDD_Fill( ( void * ) BOARD_LCD_BASE, COLOR_WHITE );\r
267         LCDD_DrawString( ( void * ) BOARD_LCD_BASE, 1, ulY + 3, "  www.FreeRTOS.org", COLOR_BLACK );\r
268 \r
269         for( ;; )\r
270         {\r
271                 /* Wait for a message from the check function (which is executed in\r
272                 the tick hook). */\r
273                 xQueueReceive( xLCDQueue, &xMessage, portMAX_DELAY );\r
274 \r
275                 /* Clear the space where the old message was. */\r
276         LCDD_DrawRectangle( ( void * ) BOARD_LCD_BASE, 0, ulY, ulWidth, ulHeight, COLOR_WHITE );\r
277 \r
278                 /* Increment to the next drawing position. */\r
279                 ulY += ulYIncrement;\r
280 \r
281                 /* Have the Y position moved past the end of the LCD? */\r
282                 if( ulY >= ulMaxY )\r
283                 {\r
284                         ulY = 0;\r
285                 }\r
286 \r
287                 /* Draw a new rectangle, in which the message will be written. */\r
288         LCDD_DrawRectangle( ( void * ) BOARD_LCD_BASE, 0, ulY, ulWidth, ulHeight, COLOR_GREEN );\r
289 \r
290                 /* Write the message. */\r
291         LCDD_DrawString( ( void * ) BOARD_LCD_BASE, ulX, ulY + 3, xMessage.pcMessage, COLOR_BLACK );\r
292         }\r
293 }\r