]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main_full.c
Add Xtensa port
[freertos] / FreeRTOS / Demo / Tensilica_Simulator_Xplorer_XCC / main_full.c
1 /*\r
2  * FreeRTOS Kernel V10.0.1\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.\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  * main() creates all the demo application tasks, then starts the scheduler.\r
30  * The web documentation provides more details of the standard demo application\r
31  * tasks, which provide no particular functionality but do provide a good\r
32  * example of how to use the FreeRTOS API.\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  * "Check" task - This only executes every five seconds but has a high priority\r
38  * to ensure it gets processor time.  Its main function is to check that all the\r
39  * standard demo tasks are still operational.  While no errors have been\r
40  * discovered the check task will print out "OK" and the current simulated tick\r
41  * time.  If an error is discovered in the execution of a task then the check\r
42  * task will print out an appropriate error message.\r
43  *\r
44  */\r
45 \r
46 \r
47 /* Standard includes. */\r
48 #include <stdio.h>\r
49 #include <stdlib.h>\r
50 \r
51 /* Kernel includes. */\r
52 #include <FreeRTOS.h>\r
53 #include <task.h>\r
54 #include <queue.h>\r
55 #include <timers.h>\r
56 #include <semphr.h>\r
57 \r
58 /* Standard demo includes. */\r
59 #include "BlockQ.h"\r
60 #include "integer.h"\r
61 #include "semtest.h"\r
62 #include "PollQ.h"\r
63 #include "GenQTest.h"\r
64 #include "QPeek.h"\r
65 #include "recmutex.h"\r
66 #include "flop.h"\r
67 #include "TimerDemo.h"\r
68 #include "countsem.h"\r
69 #include "death.h"\r
70 #include "QueueSet.h"\r
71 #include "QueueOverwrite.h"\r
72 #include "EventGroupsDemo.h"\r
73 #include "IntSemTest.h"\r
74 #include "TaskNotify.h"\r
75 #include "QueueSetPolling.h"\r
76 #include "StaticAllocation.h"\r
77 #include "blocktim.h"\r
78 #include "AbortDelay.h"\r
79 #include "MessageBufferDemo.h"\r
80 #include "StreamBufferDemo.h"\r
81 #include "StreamBufferInterrupt.h"\r
82 \r
83 /* Priorities at which the tasks are created. */\r
84 #define mainCHECK_TASK_PRIORITY                 ( configMAX_PRIORITIES - 2 )\r
85 #define mainQUEUE_POLL_PRIORITY                 ( tskIDLE_PRIORITY + 1 )\r
86 #define mainSEM_TEST_PRIORITY                   ( tskIDLE_PRIORITY + 1 )\r
87 #define mainBLOCK_Q_PRIORITY                    ( tskIDLE_PRIORITY + 2 )\r
88 #define mainCREATOR_TASK_PRIORITY               ( tskIDLE_PRIORITY + 3 )\r
89 #define mainFLASH_TASK_PRIORITY                 ( tskIDLE_PRIORITY + 1 )\r
90 #define mainINTEGER_TASK_PRIORITY               ( tskIDLE_PRIORITY )\r
91 #define mainGEN_QUEUE_TASK_PRIORITY             ( tskIDLE_PRIORITY )\r
92 #define mainFLOP_TASK_PRIORITY                  ( tskIDLE_PRIORITY )\r
93 #define mainQUEUE_OVERWRITE_PRIORITY    ( tskIDLE_PRIORITY )\r
94 \r
95 #define mainTIMER_TEST_PERIOD                   ( 50 )\r
96 \r
97 /* Parameters that are passed into the register check tasks solely for the\r
98 purpose of ensuring parameters are passed into tasks correctly. */\r
99 #define mainREG_TEST_TASK_1_PARAMETER   ( ( void * ) 0x12345678 )\r
100 #define mainREG_TEST_TASK_2_PARAMETER   ( ( void * ) 0x87654321 )\r
101 \r
102 /* Whether or not to enable interrupt queue tests. */\r
103 #define mainENABLE_INT_QUEUE_TESTS              ( 0 )\r
104 \r
105 /* The task that periodically checks that all the standard demo tasks are\r
106  * still executing and error free.\r
107  */\r
108 static void prvCheckTask( void *pvParameters );\r
109 \r
110 /* Tasks that implement register tests. */\r
111 static void prvRegTest1Task( void *pvParameters );\r
112 static void prvRegTest2Task( void *pvParameters );\r
113 \r
114 /* Functions implemented in assembly file regtest_xtensa.S. */\r
115 extern void vRegTest1( void );\r
116 extern void vRegTest2( void );\r
117 /*-----------------------------------------------------------*/\r
118 \r
119 /* The variable into which error messages are latched. */\r
120 static char *pcStatusMessage = "No errors";\r
121 \r
122 /* The following two variables are used to communicate the status of the\r
123 register check tasks to the check task.  If the variables keep incrementing,\r
124 then the register check tasks have not discovered any errors.  If a variable\r
125 stops incrementing, then an error has been found. */\r
126 volatile unsigned long ulRegTest1Counter = 0UL, ulRegTest2Counter = 0UL;\r
127 \r
128 /* The following variable is used to communicate whether the timers for the\r
129 IntQueue tests have been Initialized. This is needed to ensure that the queues\r
130 are accessed from the tick hook only after they have been created in the\r
131 interrupt queue test. */\r
132 volatile BaseType_t xTimerForQueueTestInitialized = pdFALSE;\r
133 /*-----------------------------------------------------------*/\r
134 \r
135 int main_full( void )\r
136 {\r
137         /* Start the check task as described at the top of this file. */\r
138         xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
139 \r
140         #if( mainENABLE_INT_QUEUE_TESTS == 0 )\r
141         {\r
142                 /* Create the standard demo tasks. */\r
143                 vStartTaskNotifyTask();\r
144                 vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
145                 vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
146                 vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
147                 vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );\r
148                 vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );\r
149 \r
150                 vStartQueuePeekTasks();\r
151                 vStartMathTasks( mainFLOP_TASK_PRIORITY );\r
152                 vStartRecursiveMutexTasks();\r
153                 vStartCountingSemaphoreTasks();\r
154                 vStartQueueSetTasks();\r
155 \r
156                 vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );\r
157                 vStartEventGroupTasks();\r
158                 vStartInterruptSemaphoreTasks();\r
159                 vStartQueueSetPollingTask();\r
160                 vCreateBlockTimeTasks();\r
161 \r
162                 #if( configUSE_PREEMPTION != 0  )\r
163                 {\r
164                         /* Don't expect these tasks to pass when preemption is not used. */\r
165                         vStartTimerDemoTask( mainTIMER_TEST_PERIOD );\r
166                 }\r
167                 #endif\r
168 \r
169                 vCreateAbortDelayTasks();\r
170                 vStartMessageBufferTasks( configMINIMAL_STACK_SIZE );\r
171 \r
172                 vStartStreamBufferTasks();\r
173                 vStartStreamBufferInterruptDemo();\r
174 \r
175                 /* Create the register check tasks, as described at the top of this     file */\r
176                 xTaskCreate( prvRegTest1Task, "Reg1", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_1_PARAMETER, tskIDLE_PRIORITY, NULL );\r
177                 xTaskCreate( prvRegTest2Task, "Reg2", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL );\r
178 \r
179                 /* The suicide tasks must be created last as they need to know how many\r
180                 tasks were running prior to their creation.  This then allows them to\r
181                 ascertain whether or not the correct/expected number of tasks are running at\r
182                 any given time. */\r
183                 vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );\r
184         }\r
185         #else /* mainENABLE_INT_QUEUE_TESTS */\r
186         {\r
187                 /* Start interrupt queue test tasks. */\r
188                 vStartInterruptQueueTasks();\r
189         }\r
190         #endif /* mainENABLE_INT_QUEUE_TESTS */\r
191 \r
192         /* Start the scheduler itself. */\r
193         vTaskStartScheduler();\r
194 \r
195         /* Should never get here unless there was not enough heap space to create\r
196         the idle and other system tasks. */\r
197         return 0;\r
198 }\r
199 /*-----------------------------------------------------------*/\r
200 \r
201 static void prvCheckTask( void *pvParameters )\r
202 {\r
203 TickType_t xNextWakeTime;\r
204 const TickType_t xCycleFrequency = pdMS_TO_TICKS( 5000UL );\r
205 static unsigned long ulLastRegTest1Value = 0, ulLastRegTest2Value = 0;\r
206 \r
207         /* Just to remove compiler warning. */\r
208         ( void ) pvParameters;\r
209 \r
210         /* Initialise xNextWakeTime - this only needs to be done once. */\r
211         xNextWakeTime = xTaskGetTickCount();\r
212 \r
213         for( ;; )\r
214         {\r
215                 /* Place this task in the blocked state until it is time to run again. */\r
216                 vTaskDelayUntil( &xNextWakeTime, xCycleFrequency );\r
217 \r
218                 #if( mainENABLE_INT_QUEUE_TESTS == 0 )\r
219                 {\r
220                         /* Check the standard demo tasks are running without error. */\r
221                         #if( configUSE_PREEMPTION != 0 )\r
222                         {\r
223                                 /* These tasks are only created when preemption is used. */\r
224                                 if( xAreTimerDemoTasksStillRunning( xCycleFrequency ) != pdTRUE )\r
225                                 {\r
226                                         pcStatusMessage = "Error: TimerDemo";\r
227                                 }\r
228                         }\r
229                         #endif\r
230 \r
231                         if( xAreTaskNotificationTasksStillRunning() != pdTRUE )\r
232                         {\r
233                                 pcStatusMessage = "Error:  Notification";\r
234                         }\r
235                         else if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
236                         {\r
237                                 pcStatusMessage = "Error: BlockQueue";\r
238                         }\r
239                         else if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
240                         {\r
241                                 pcStatusMessage = "Error: SemTest";\r
242                         }\r
243                         else if( xArePollingQueuesStillRunning() != pdTRUE )\r
244                         {\r
245                                 pcStatusMessage = "Error: PollQueue";\r
246                         }\r
247                         else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
248                         {\r
249                                 pcStatusMessage = "Error: IntMath";\r
250                         }\r
251                         else if( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
252                         {\r
253                                 pcStatusMessage = "Error: GenQueue";\r
254                         }\r
255                         else if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
256                         {\r
257                                 pcStatusMessage = "Error: QueuePeek";\r
258                         }\r
259                         else if( xAreMathsTaskStillRunning() != pdPASS )\r
260                         {\r
261                                 pcStatusMessage = "Error: Flop";\r
262                         }\r
263                         else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
264                         {\r
265                                 pcStatusMessage = "Error: RecMutex";\r
266                         }\r
267                         else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )\r
268                         {\r
269                                 pcStatusMessage = "Error: CountSem";\r
270                         }\r
271                         else if( xAreQueueSetTasksStillRunning() != pdPASS )\r
272                         {\r
273                                 pcStatusMessage = "Error: Queue set";\r
274                         }\r
275                         else if( xIsQueueOverwriteTaskStillRunning() != pdPASS )\r
276                         {\r
277                                 pcStatusMessage = "Error: Queue overwrite";\r
278                         }\r
279                         else if( xAreEventGroupTasksStillRunning() != pdTRUE )\r
280                         {\r
281                                 pcStatusMessage = "Error: EventGroup";\r
282                         }\r
283                         else if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE )\r
284                         {\r
285                                 pcStatusMessage = "Error: IntSem";\r
286                         }\r
287                         else if( xAreQueueSetPollTasksStillRunning() != pdPASS )\r
288                         {\r
289                                 pcStatusMessage = "Error: Queue set polling";\r
290                         }\r
291                         else if( xAreBlockTimeTestTasksStillRunning() != pdPASS )\r
292                         {\r
293                                 pcStatusMessage = "Error: Block time";\r
294                         }\r
295                         else if( xAreAbortDelayTestTasksStillRunning() != pdPASS )\r
296                         {\r
297                                 pcStatusMessage = "Error: Abort delay";\r
298                         }\r
299                         else if( xAreMessageBufferTasksStillRunning() != pdTRUE )\r
300                         {\r
301                                 pcStatusMessage = "Error:  MessageBuffer";\r
302                         }\r
303                         else if( xAreStreamBufferTasksStillRunning() != pdTRUE )\r
304                         {\r
305                                 pcStatusMessage = "Error:  StreamBuffer";\r
306                         }\r
307                         else if( xIsInterruptStreamBufferDemoStillRunning() != pdPASS )\r
308                         {\r
309                                 pcStatusMessage = "Error: Stream buffer interrupt";\r
310                         }\r
311                         else if( xIsCreateTaskStillRunning() != pdTRUE )\r
312                         {\r
313                                 pcStatusMessage = "Error: Death";\r
314                         }\r
315                         else if( ulLastRegTest1Value == ulRegTest1Counter )\r
316                         {\r
317                                 pcStatusMessage = "Error: Reg Test 1";\r
318                         }\r
319                         else if( ulLastRegTest2Value == ulRegTest2Counter )\r
320                         {\r
321                                 pcStatusMessage = "Error: Reg Test 2";\r
322                         }\r
323 \r
324                         /* Update register test counters. */\r
325                         ulLastRegTest1Value = ulRegTest1Counter;\r
326                         ulLastRegTest2Value = ulRegTest2Counter;\r
327                 }\r
328                 #else /* mainENABLE_INT_QUEUE_TESTS */\r
329                 {\r
330                         if( xAreIntQueueTasksStillRunning() != pdTRUE )\r
331                         {\r
332                                 pcStatusMessage = "Error: IntQueue";\r
333                         }\r
334                 }\r
335                 #endif /* mainENABLE_INT_QUEUE_TESTS */\r
336 \r
337                 /* This is the only task that uses stdout so its ok to call printf()\r
338                 directly. */\r
339                 printf( "%s - tick count %zu - free heap %zu - min free heap %zu\r\n", pcStatusMessage,\r
340                                                                                                                                                            xTaskGetTickCount(),\r
341                                                                                                                                                            xPortGetFreeHeapSize(),\r
342                                                                                                                                                            xPortGetMinimumEverFreeHeapSize() );\r
343         }\r
344 }\r
345 /*-----------------------------------------------------------*/\r
346 \r
347 /* Called by vApplicationTickHook(), which is defined in main.c. */\r
348 void vFullDemoTickHookFunction( void )\r
349 {\r
350 TaskHandle_t xTimerTask;\r
351 \r
352         #if( mainENABLE_INT_QUEUE_TESTS == 0 )\r
353         {\r
354                 /* Exercise using task notifications from an interrupt. */\r
355                 xNotifyTaskFromISR();\r
356 \r
357                 /* Write to a queue that is in use as part of the queue set demo to\r
358                  * demonstrate using queue sets from an ISR. */\r
359                 vQueueSetAccessQueueSetFromISR();\r
360 \r
361                 /* Call the periodic queue overwrite from ISR demo. */\r
362                 vQueueOverwritePeriodicISRDemo();\r
363 \r
364                 /* Exercise event groups from interrupts. */\r
365                 vPeriodicEventGroupsProcessing();\r
366 \r
367                 /* Exercise giving mutexes from an interrupt. */\r
368                 vInterruptSemaphorePeriodicTest();\r
369 \r
370                 /* Queue set access from interrupt. */\r
371                 vQueueSetPollingInterruptAccess();\r
372 \r
373                 /* Call the periodic timer test, which tests the timer API functions that\r
374                 can be called from an ISR. */\r
375                 #if( configUSE_PREEMPTION != 0 )\r
376                 {\r
377                         /* Only created when preemption is used. */\r
378                         vTimerPeriodicISRTests();\r
379                 }\r
380                 #endif\r
381 \r
382                 /* Writes to stream buffer byte by byte to test the stream buffer trigger\r
383                 level functionality. */\r
384                 vPeriodicStreamBufferProcessing();\r
385 \r
386                 /* Writes a string to a string buffer four bytes at a time to demonstrate\r
387                 a stream being sent from an interrupt to a task. */\r
388                 vBasicStreamBufferSendFromISR();\r
389         }\r
390         #else /* mainENABLE_INT_QUEUE_TESTS */\r
391         {\r
392                 /* Access queues from interrupt. Make sure to access after the queues have\r
393                 been created. */\r
394                 if( xTimerForQueueTestInitialized == pdTRUE )\r
395                 {\r
396                         portYIELD_FROM_ISR( xFirstTimerHandler() );\r
397                 }\r
398         }\r
399         #endif /* mainENABLE_INT_QUEUE_TESTS */\r
400 }\r
401 /*-----------------------------------------------------------*/\r
402 \r
403 static void prvRegTest1Task( void *pvParameters )\r
404 {\r
405         /* Although the regtest task is written in assembly, its entry point is\r
406         written in C for convenience of checking the task parameter is being passed\r
407         in correctly. */\r
408         if( pvParameters == mainREG_TEST_TASK_1_PARAMETER )\r
409         {\r
410                 /* Start the part of the test that is written in assembly. */\r
411                 vRegTest1();\r
412         }\r
413 \r
414         /* The following line will only execute if the task parameter is found to\r
415         be incorrect.  The check task will detect that the regtest loop counter is\r
416         not being incremented and flag an error. */\r
417         vTaskDelete( NULL );\r
418 }\r
419 /*-----------------------------------------------------------*/\r
420 \r
421 static void prvRegTest2Task( void *pvParameters )\r
422 {\r
423         /* Although the regtest task is written in assembly, its entry point is\r
424         written in C for convenience of checking the task parameter is being passed\r
425         in correctly. */\r
426         if( pvParameters == mainREG_TEST_TASK_2_PARAMETER )\r
427         {\r
428                 /* Start the part of the test that is written in assembly. */\r
429                 vRegTest2();\r
430         }\r
431 \r
432         /* The following line will only execute if the task parameter is found to\r
433         be incorrect.  The check task will detect that the regtest loop counter is\r
434         not being incremented and flag an error. */\r
435         vTaskDelete( NULL );\r
436 }\r
437 /*-----------------------------------------------------------*/\r