]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/ARM7_LPC2138_Rowley/main.c
Update license information text files for the CLI, TCP and UDP products to be correct...
[freertos] / FreeRTOS / Demo / ARM7_LPC2138_Rowley / 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  * This file contains a demo created to execute on the Rowley Associates\r
31  * LPC2138 CrossFire development board.\r
32  *\r
33  * main() creates all the demo application tasks, then starts the scheduler.\r
34  * The WEB documentation provides more details of the standard demo application\r
35  * tasks.\r
36  *\r
37  * Main.c also creates a task called "Check".  This only executes every few\r
38  * seconds but has a high priority so is guaranteed to get processor time.\r
39  * Its function is to check that all the other tasks are still operational.\r
40  * Each standard demo task maintains a unique count that is incremented each\r
41  * time the task successfully completes its function.  Should any error occur\r
42  * within such a task the count is permanently halted.  The check task inspects\r
43  * the count of each task to ensure it has changed since the last time the\r
44  * check task executed.  If all the count variables have changed all the tasks\r
45  * are still executing error free, and the check task writes "PASS" to the\r
46  * CrossStudio terminal IO window.  Should any task contain an error at any time\r
47  * the error is latched and "FAIL" written to the terminal IO window.\r
48  *\r
49  * Finally, main() sets up an interrupt service routine and task to handle\r
50  * pushes of the button that is built into the CrossFire board.  When the button\r
51  * is pushed the ISR wakes the button task - which generates a table of task\r
52  * status information which is also displayed on the terminal IO window.\r
53  *\r
54  * A print task is defined to ensure exclusive and consistent access to the\r
55  * terminal IO.  This is the only task that is allowed to access the terminal.\r
56  * The check and button task therefore do not access the terminal directly but\r
57  * instead pass a pointer to the message they wish to display to the print task.\r
58  */\r
59 \r
60 /* Standard includes. */\r
61 #include <__cross_studio_io.h>\r
62 \r
63 /* Scheduler includes. */\r
64 #include "FreeRTOS.h"\r
65 #include "task.h"\r
66 #include "queue.h"\r
67 #include "semphr.h"\r
68 \r
69 /* Demo app includes. */\r
70 #include "BlockQ.h"\r
71 #include "death.h"\r
72 #include "dynamic.h"\r
73 #include "integer.h"\r
74 #include "PollQ.h"\r
75 #include "blocktim.h"\r
76 #include "recmutex.h"\r
77 #include "semtest.h"\r
78 \r
79 /* Hardware configuration definitions. */\r
80 #define mainBUS_CLK_FULL                                        ( ( unsigned char ) 0x01 )\r
81 #define mainLED_BIT                                                     0x80000000\r
82 #define mainP0_14__EINT_1                                       ( 2 << 28 )\r
83 #define mainEINT_1_EDGE_SENSITIVE                       2\r
84 #define mainEINT_1_FALLING_EDGE_SENSITIVE       0\r
85 #define mainEINT_1_CHANNEL                                      15\r
86 #define mainEINT_1_VIC_CHANNEL_BIT                      ( 1 << mainEINT_1_CHANNEL )\r
87 #define mainEINT_1_ENABLE_BIT                           ( 1 << 5 )\r
88 \r
89 /* Demo application definitions. */\r
90 #define mainQUEUE_SIZE                                          ( 3 )\r
91 #define mainLED_DELAY                                           ( ( TickType_t ) 500 / portTICK_PERIOD_MS )\r
92 #define mainERROR_LED_DELAY                                     ( ( TickType_t ) 50 / portTICK_PERIOD_MS )\r
93 #define mainCHECK_DELAY                                         ( ( TickType_t ) 5000 / portTICK_PERIOD_MS )\r
94 #define mainLIST_BUFFER_SIZE                            2048\r
95 #define mainNO_DELAY                                            ( 0 )\r
96 #define mainSHORT_DELAY                                         ( 150 / portTICK_PERIOD_MS )\r
97 \r
98 /* Task priorities. */\r
99 #define mainLED_TASK_PRIORITY                           ( tskIDLE_PRIORITY + 2 )\r
100 #define mainQUEUE_POLL_PRIORITY                         ( tskIDLE_PRIORITY + 2 )\r
101 #define mainCHECK_TASK_PRIORITY                         ( tskIDLE_PRIORITY + 3 )\r
102 #define mainSEM_TEST_PRIORITY                           ( tskIDLE_PRIORITY + 1 )\r
103 #define mainBLOCK_Q_PRIORITY                            ( tskIDLE_PRIORITY + 2 )\r
104 #define mainPRINT_TASK_PRIORITY                         ( tskIDLE_PRIORITY + 0 )\r
105 \r
106 /*-----------------------------------------------------------*/\r
107 \r
108 /* The semaphore used to wake the button task from within the external interrupt\r
109 handler. */\r
110 SemaphoreHandle_t xButtonSemaphore;\r
111 \r
112 /* The queue that is used to send message to vPrintTask for display in the\r
113 terminal output window. */\r
114 QueueHandle_t xPrintQueue;\r
115 \r
116 /* The rate at which the LED will toggle.  The toggle rate increases if an\r
117 error is detected in any task. */\r
118 static TickType_t xLED_Delay = mainLED_DELAY;\r
119 /*-----------------------------------------------------------*/\r
120 \r
121 /*\r
122  * Simply flashes the on board LED every mainLED_DELAY milliseconds.\r
123  */\r
124 static void vLEDTask( void *pvParameters );\r
125 \r
126 /*\r
127  * Checks the status of all the demo tasks then prints a message to the\r
128  * CrossStudio terminal IO windows.  The message will be either PASS or FAIL\r
129  * depending on the status of the demo applications tasks.  A FAIL status will\r
130  * be latched.\r
131  *\r
132  * Messages are not written directly to the terminal, but passed to vPrintTask\r
133  * via a queue.\r
134  */\r
135 static void vCheckTask( void *pvParameters );\r
136 \r
137 /*\r
138  * Controls all terminal output.  If a task wants to send a message to the\r
139  * terminal IO it posts a pointer to the text to vPrintTask via a queue.  This\r
140  * ensures serial access to the terminal IO.\r
141  */\r
142 static void vPrintTask( void *pvParameter );\r
143 \r
144 /*\r
145  * Simply waits for an interrupt to be generated from the built in button, then\r
146  * generates a table of tasks states that is then written by vPrintTask to the\r
147  * terminal output window within CrossStudio.\r
148  */\r
149 static void vButtonHandlerTask( void *pvParameters );\r
150 \r
151 /*-----------------------------------------------------------*/\r
152 \r
153 int main( void )\r
154 {\r
155         /* Setup the peripheral bus to be the same as the PLL output. */\r
156         VPBDIV = mainBUS_CLK_FULL;\r
157 \r
158         /* Create the queue used to pass message to vPrintTask. */\r
159         xPrintQueue = xQueueCreate( mainQUEUE_SIZE, sizeof( char * ) );\r
160 \r
161         /* Create the semaphore used to wake vButtonHandlerTask(). */\r
162         vSemaphoreCreateBinary( xButtonSemaphore );\r
163         xSemaphoreTake( xButtonSemaphore, 0 );\r
164 \r
165         /* Start the standard demo tasks. */\r
166         vStartIntegerMathTasks( tskIDLE_PRIORITY );\r
167         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
168         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
169         vStartDynamicPriorityTasks();\r
170         vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
171 \r
172         #if configUSE_PREEMPTION == 1\r
173         {\r
174                 /* The timing of console output when not using the preemptive\r
175                 scheduler causes the block time tests to detect a timing problem. */\r
176                 vCreateBlockTimeTasks();\r
177         }\r
178         #endif\r
179 \r
180     vStartRecursiveMutexTasks();\r
181 \r
182         /* Start the tasks defined within this file. */\r
183         xTaskCreate( vLEDTask, "LED", configMINIMAL_STACK_SIZE, NULL, mainLED_TASK_PRIORITY, NULL );\r
184     xTaskCreate( vCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
185     xTaskCreate( vPrintTask, "Print", configMINIMAL_STACK_SIZE, NULL, mainPRINT_TASK_PRIORITY, NULL );\r
186     xTaskCreate( vButtonHandlerTask, "Button", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
187 \r
188         /* Start the scheduler. */\r
189         vTaskStartScheduler();\r
190 \r
191         /* The scheduler should now be running, so we will only ever reach here if we\r
192         ran out of heap space. */\r
193 \r
194         return 0;\r
195 }\r
196 /*-----------------------------------------------------------*/\r
197 \r
198 static void vLEDTask( void *pvParameters )\r
199 {\r
200         /* Just to remove compiler warnings. */\r
201         ( void ) pvParameters;\r
202 \r
203         /* Configure IO. */\r
204         IO0DIR |= mainLED_BIT;\r
205         IO0SET = mainLED_BIT;\r
206 \r
207         for( ;; )\r
208         {\r
209                 /* Not very exiting - just delay... */\r
210                 vTaskDelay( xLED_Delay );\r
211 \r
212                 /* ...set the IO ... */\r
213         IO0CLR = mainLED_BIT;\r
214 \r
215                 /* ...delay again... */\r
216                 vTaskDelay( xLED_Delay );\r
217 \r
218                 /* ...then clear the IO. */\r
219                 IO0SET = mainLED_BIT;\r
220         }\r
221 }\r
222 /*-----------------------------------------------------------*/\r
223 \r
224 static void vCheckTask( void *pvParameters )\r
225 {\r
226 portBASE_TYPE xErrorOccurred = pdFALSE;\r
227 TickType_t xLastExecutionTime;\r
228 const char * const pcPassMessage = "PASS\n";\r
229 const char * const pcFailMessage = "FAIL\n";\r
230 \r
231         /* Just to remove compiler warnings. */\r
232         ( void ) pvParameters;\r
233 \r
234         /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()\r
235         works correctly. */\r
236         xLastExecutionTime = xTaskGetTickCount();\r
237 \r
238         for( ;; )\r
239         {\r
240                 /* Perform this check every mainCHECK_DELAY milliseconds. */\r
241                 vTaskDelayUntil( &xLastExecutionTime, mainCHECK_DELAY );\r
242 \r
243                 /* Has an error been found in any task? */\r
244 \r
245                 if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
246                 {\r
247                         xErrorOccurred = pdTRUE;\r
248                 }\r
249 \r
250                 if( xArePollingQueuesStillRunning() != pdTRUE )\r
251                 {\r
252                         xErrorOccurred = pdTRUE;\r
253                 }\r
254 \r
255                 if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
256                 {\r
257                         xErrorOccurred = pdTRUE;\r
258                 }\r
259 \r
260                 if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )\r
261                 {\r
262                         xErrorOccurred = pdTRUE;\r
263                 }\r
264 \r
265                 if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
266                 {\r
267                         xErrorOccurred = pdTRUE;\r
268                 }\r
269 \r
270                 #if configUSE_PREEMPTION == 1\r
271                 {\r
272                         /* The timing of console output when not using the preemptive\r
273                         scheduler causes the block time tests to detect a timing problem. */\r
274                         if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )\r
275                         {\r
276                                 xErrorOccurred = pdTRUE;\r
277                         }\r
278                 }\r
279                 #endif\r
280 \r
281                 if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
282                 {\r
283                         xErrorOccurred = pdTRUE;\r
284                 }\r
285 \r
286                 /* Send either a pass or fail message.  If an error is found it is\r
287                 never cleared again. */\r
288                 if( xErrorOccurred == pdTRUE )\r
289                 {\r
290                         xLED_Delay = mainERROR_LED_DELAY;\r
291                         xQueueSend( xPrintQueue, &pcFailMessage, portMAX_DELAY );\r
292                 }\r
293                 else\r
294                 {\r
295                         xQueueSend( xPrintQueue, &pcPassMessage, portMAX_DELAY );\r
296                 }\r
297         }\r
298 }\r
299 /*-----------------------------------------------------------*/\r
300 \r
301 static void vPrintTask( void *pvParameters )\r
302 {\r
303 char *pcMessage;\r
304 \r
305         /* Just to stop compiler warnings. */\r
306         ( void ) pvParameters;\r
307 \r
308         for( ;; )\r
309         {\r
310                 /* Wait for a message to arrive. */\r
311                 while( xQueueReceive( xPrintQueue, &pcMessage, portMAX_DELAY ) != pdPASS );\r
312 \r
313                 /* Write the message to the terminal IO. */\r
314                 #ifndef NDEBUG\r
315                         debug_printf( "%s", pcMessage );\r
316                 #endif\r
317         }\r
318 }\r
319 /*-----------------------------------------------------------*/\r
320 \r
321 static void vButtonHandlerTask( void *pvParameters )\r
322 {\r
323 static char cListBuffer[ mainLIST_BUFFER_SIZE ];\r
324 const char *pcList = &( cListBuffer[ 0 ] );\r
325 const char * const pcHeader = "\nTask          State  Priority  Stack   #\n************************************************";\r
326 extern void (vButtonISRWrapper) ( void );\r
327 \r
328         /* Just to stop compiler warnings. */\r
329         ( void ) pvParameters;\r
330 \r
331         /* Configure the interrupt. */\r
332         portENTER_CRITICAL();\r
333         {\r
334                 /* Configure P0.14 to generate interrupts. */\r
335                 PINSEL0 |= mainP0_14__EINT_1;\r
336                 EXTMODE = mainEINT_1_EDGE_SENSITIVE;\r
337                 EXTPOLAR = mainEINT_1_FALLING_EDGE_SENSITIVE;\r
338 \r
339                 /* Setup the VIC for EINT 1. */\r
340                 VICIntSelect &= ~mainEINT_1_VIC_CHANNEL_BIT;\r
341                 VICIntEnable |= mainEINT_1_VIC_CHANNEL_BIT;\r
342                 VICVectAddr1 = ( long ) vButtonISRWrapper;\r
343                 VICVectCntl1 = mainEINT_1_ENABLE_BIT | mainEINT_1_CHANNEL;\r
344         }\r
345         portEXIT_CRITICAL();\r
346 \r
347         for( ;; )\r
348         {\r
349                 /* For debouncing, wait a while then clear the semaphore. */\r
350                 vTaskDelay( mainSHORT_DELAY );\r
351                 xSemaphoreTake( xButtonSemaphore, mainNO_DELAY );\r
352 \r
353                 /* Wait for an interrupt. */\r
354                 xSemaphoreTake( xButtonSemaphore, portMAX_DELAY );\r
355 \r
356                 /* Send the column headers to the print task for display. */\r
357                 xQueueSend( xPrintQueue, &pcHeader, portMAX_DELAY );\r
358 \r
359                 /* Create the list of task states. */\r
360                 vTaskList( cListBuffer );\r
361 \r
362                 /* Send the task status information to the print task for display. */\r
363                 xQueueSend( xPrintQueue, &pcList, portMAX_DELAY );\r
364         }\r
365 }\r
366 /*-----------------------------------------------------------*/\r
367 \r
368 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )\r
369 {\r
370         /* Check pcTaskName for the name of the offending task, or pxCurrentTCB\r
371         if pcTaskName has itself been corrupted. */\r
372         ( void ) pxTask;\r
373         ( void ) pcTaskName;\r
374         for( ;; );\r
375 }\r
376 \r
377 \r
378 \r
379 \r
380 \r
381 \r