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