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