]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_LM3S811_GCC/main.c
Update to V5.1.2.
[freertos] / Demo / CORTEX_LM3S811_GCC / main.c
1 /*\r
2         FreeRTOS.org V5.1.2 - Copyright (C) 2003-2009 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS.org is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS.org; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS.org, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section\r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26     ***************************************************************************\r
27     ***************************************************************************\r
28     *                                                                         *\r
29     * Get the FreeRTOS eBook!  See http://www.FreeRTOS.org/Documentation      *\r
30         *                                                                         *\r
31         * This is a concise, step by step, 'hands on' guide that describes both   *\r
32         * general multitasking concepts and FreeRTOS specifics. It presents and   *\r
33         * explains numerous examples that are written using the FreeRTOS API.     *\r
34         * Full source code for all the examples is provided in an accompanying    *\r
35         * .zip file.                                                              *\r
36     *                                                                         *\r
37     ***************************************************************************\r
38     ***************************************************************************\r
39 \r
40         Please ensure to read the configuration and relevant port sections of the\r
41         online documentation.\r
42 \r
43         http://www.FreeRTOS.org - Documentation, latest information, license and \r
44         contact details.\r
45 \r
46         http://www.SafeRTOS.com - A version that is certified for use in safety \r
47         critical systems.\r
48 \r
49         http://www.OpenRTOS.com - Commercial support, development, porting, \r
50         licensing and training services.\r
51 */\r
52 \r
53 \r
54 /*\r
55  * This project contains an application demonstrating the use of the\r
56  * FreeRTOS.org mini real time scheduler on the Luminary Micro LM3S811 Eval\r
57  * board.  See http://www.FreeRTOS.org for more information.\r
58  *\r
59  * main() simply sets up the hardware, creates all the demo application tasks,\r
60  * then starts the scheduler.  http://www.freertos.org/a00102.html provides\r
61  * more information on the standard demo tasks.\r
62  *\r
63  * In addition to a subset of the standard demo application tasks, main.c also\r
64  * defines the following tasks:\r
65  *\r
66  * + A 'Print' task.  The print task is the only task permitted to access the\r
67  * LCD - thus ensuring mutual exclusion and consistent access to the resource.\r
68  * Other tasks do not access the LCD directly, but instead send the text they\r
69  * wish to display to the print task.  The print task spends most of its time\r
70  * blocked - only waking when a message is queued for display.\r
71  *\r
72  * + A 'Button handler' task.  The eval board contains a user push button that\r
73  * is configured to generate interrupts.  The interrupt handler uses a\r
74  * semaphore to wake the button handler task - demonstrating how the priority\r
75  * mechanism can be used to defer interrupt processing to the task level.  The\r
76  * button handler task sends a message both to the LCD (via the print task) and\r
77  * the UART where it can be viewed using a dumb terminal (via the UART to USB\r
78  * converter on the eval board).  NOTES:  The dumb terminal must be closed in\r
79  * order to reflash the microcontroller.  A very basic interrupt driven UART\r
80  * driver is used that does not use the FIFO.  19200 baud is used.\r
81  *\r
82  * + A 'check' task.  The check task only executes every five seconds but has a\r
83  * high priority so is guaranteed to get processor time.  Its function is to\r
84  * check that all the other tasks are still operational and that no errors have\r
85  * been detected at any time.  If no errors have every been detected 'PASS' is\r
86  * written to the display (via the print task) - if an error has ever been\r
87  * detected the message is changed to 'FAIL'.  The position of the message is\r
88  * changed for each write.\r
89  */\r
90 \r
91 \r
92 \r
93 /* Environment includes. */\r
94 #include "DriverLib.h"\r
95 \r
96 /* Scheduler includes. */\r
97 #include "FreeRTOS.h"\r
98 #include "task.h"\r
99 #include "queue.h"\r
100 #include "semphr.h"\r
101 \r
102 /* Demo app includes. */\r
103 #include "integer.h"\r
104 #include "PollQ.h"\r
105 #include "semtest.h"\r
106 #include "BlockQ.h"\r
107 \r
108 /* Delay between cycles of the 'check' task. */\r
109 #define mainCHECK_DELAY                                         ( ( portTickType ) 5000 / portTICK_RATE_MS )\r
110 \r
111 /* UART configuration - note this does not use the FIFO so is not very\r
112 efficient. */\r
113 #define mainBAUD_RATE                           ( 19200 )\r
114 #define mainFIFO_SET                            ( 0x10 )\r
115 \r
116 /* Demo task priorities. */\r
117 #define mainQUEUE_POLL_PRIORITY         ( tskIDLE_PRIORITY + 2 )\r
118 #define mainCHECK_TASK_PRIORITY         ( tskIDLE_PRIORITY + 3 )\r
119 #define mainSEM_TEST_PRIORITY           ( tskIDLE_PRIORITY + 1 )\r
120 #define mainBLOCK_Q_PRIORITY            ( tskIDLE_PRIORITY + 2 )\r
121 \r
122 /* Demo board specifics. */\r
123 #define mainPUSH_BUTTON             GPIO_PIN_4\r
124 \r
125 /* Misc. */\r
126 #define mainQUEUE_SIZE                          ( 3 )\r
127 #define mainDEBOUNCE_DELAY                      ( ( portTickType ) 150 / portTICK_RATE_MS )\r
128 #define mainNO_DELAY                            ( ( portTickType ) 0 )\r
129 /*\r
130  * Configure the processor and peripherals for this demo.\r
131  */\r
132 static void prvSetupHardware( void );\r
133 \r
134 /*\r
135  * The 'check' task, as described at the top of this file.\r
136  */\r
137 static void vCheckTask( void *pvParameters );\r
138 \r
139 /*\r
140  * The task that is woken by the ISR that processes GPIO interrupts originating\r
141  * from the push button.\r
142  */\r
143 static void vButtonHandlerTask( void *pvParameters );\r
144 \r
145 /*\r
146  * The task that controls access to the LCD.\r
147  */\r
148 static void vPrintTask( void *pvParameter );\r
149 \r
150 /* String that is transmitted on the UART. */\r
151 static portCHAR *cMessage = "Task woken by button interrupt! --- ";\r
152 static volatile portCHAR *pcNextChar;\r
153 \r
154 /* The semaphore used to wake the button handler task from within the GPIO\r
155 interrupt handler. */\r
156 xSemaphoreHandle xButtonSemaphore;\r
157 \r
158 /* The queue used to send strings to the print task for display on the LCD. */\r
159 xQueueHandle xPrintQueue;\r
160 \r
161 /*-----------------------------------------------------------*/\r
162 \r
163 int main( void )\r
164 {\r
165         /* Configure the clocks, UART and GPIO. */\r
166         prvSetupHardware();\r
167 \r
168         /* Create the semaphore used to wake the button handler task from the GPIO\r
169         ISR. */\r
170         vSemaphoreCreateBinary( xButtonSemaphore );\r
171         xSemaphoreTake( xButtonSemaphore, 0 );\r
172 \r
173         /* Create the queue used to pass message to vPrintTask. */\r
174         xPrintQueue = xQueueCreate( mainQUEUE_SIZE, sizeof( portCHAR * ) );\r
175 \r
176         /* Start the standard demo tasks. */\r
177         vStartIntegerMathTasks( tskIDLE_PRIORITY );\r
178         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
179         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
180         vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
181 \r
182         /* Start the tasks defined within the file. */\r
183         xTaskCreate( vCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
184         xTaskCreate( vButtonHandlerTask, "Status", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY + 1, NULL );\r
185         xTaskCreate( vPrintTask, "Print", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL );\r
186 \r
187         /* Start the scheduler. */\r
188         vTaskStartScheduler();\r
189 \r
190         /* Will only get here if there was insufficient heap to start the\r
191         scheduler. */\r
192 \r
193         return 0;\r
194 }\r
195 /*-----------------------------------------------------------*/\r
196 \r
197 static void vCheckTask( void *pvParameters )\r
198 {\r
199 portBASE_TYPE xErrorOccurred = pdFALSE;\r
200 portTickType xLastExecutionTime;\r
201 const portCHAR *pcPassMessage = "PASS";\r
202 const portCHAR *pcFailMessage = "FAIL";\r
203 \r
204         /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()\r
205         works correctly. */\r
206         xLastExecutionTime = xTaskGetTickCount();\r
207 \r
208         for( ;; )\r
209         {\r
210                 /* Perform this check every mainCHECK_DELAY milliseconds. */\r
211                 vTaskDelayUntil( &xLastExecutionTime, mainCHECK_DELAY );\r
212 \r
213                 /* Has an error been found in any task? */\r
214 \r
215                 if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
216                 {\r
217                         xErrorOccurred = pdTRUE;\r
218                 }\r
219         \r
220                 if( xArePollingQueuesStillRunning() != pdTRUE )\r
221                 {\r
222                         xErrorOccurred = pdTRUE;\r
223                 }\r
224         \r
225                 if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
226                 {\r
227                         xErrorOccurred = pdTRUE;\r
228                 }\r
229 \r
230                 if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
231                 {\r
232                         xErrorOccurred = pdTRUE;\r
233                 }\r
234 \r
235                 /* Send either a pass or fail message.  If an error is found it is\r
236                 never cleared again.  We do not write directly to the LCD, but instead\r
237                 queue a message for display by the print task. */\r
238                 if( xErrorOccurred == pdTRUE )\r
239                 {\r
240                         xQueueSend( xPrintQueue, &pcFailMessage, portMAX_DELAY );\r
241                 }\r
242                 else\r
243                 {\r
244                         xQueueSend( xPrintQueue, &pcPassMessage, portMAX_DELAY );\r
245                 }\r
246         }\r
247 }\r
248 /*-----------------------------------------------------------*/\r
249 \r
250 static void prvSetupHardware( void )\r
251 {\r
252         /* Setup the PLL. */\r
253         SysCtlClockSet( SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_6MHZ );\r
254 \r
255         /* Setup the push button. */\r
256         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);\r
257     GPIODirModeSet(GPIO_PORTC_BASE, mainPUSH_BUTTON, GPIO_DIR_MODE_IN);\r
258         GPIOIntTypeSet( GPIO_PORTC_BASE, mainPUSH_BUTTON,GPIO_FALLING_EDGE );\r
259         IntPrioritySet( INT_GPIOC, configKERNEL_INTERRUPT_PRIORITY );\r
260         GPIOPinIntEnable( GPIO_PORTC_BASE, mainPUSH_BUTTON );\r
261         IntEnable( INT_GPIOC );\r
262 \r
263 \r
264 \r
265         /* Enable the UART.  */\r
266         SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);\r
267         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);\r
268 \r
269         /* Set GPIO A0 and A1 as peripheral function.  They are used to output the\r
270         UART signals. */\r
271         GPIODirModeSet( GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_DIR_MODE_HW );\r
272 \r
273         /* Configure the UART for 8-N-1 operation. */\r
274         UARTConfigSet( UART0_BASE, mainBAUD_RATE, UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE );\r
275 \r
276         /* We don't want to use the fifo.  This is for test purposes to generate\r
277         as many interrupts as possible. */\r
278         HWREG( UART0_BASE + UART_O_LCR_H ) &= ~mainFIFO_SET;\r
279 \r
280         /* Enable Tx interrupts. */\r
281         HWREG( UART0_BASE + UART_O_IM ) |= UART_INT_TX;\r
282         IntPrioritySet( INT_UART0, configKERNEL_INTERRUPT_PRIORITY );\r
283         IntEnable( INT_UART0 );\r
284 \r
285 \r
286         /* Initialise the LCD> */\r
287     OSRAMInit( false );\r
288     OSRAMStringDraw("www.FreeRTOS.org", 0, 0);\r
289         OSRAMStringDraw("LM3S811 demo", 16, 1);\r
290 }\r
291 /*-----------------------------------------------------------*/\r
292 \r
293 static void vButtonHandlerTask( void *pvParameters )\r
294 {\r
295 const portCHAR *pcInterruptMessage = "Int";\r
296 \r
297         for( ;; )\r
298         {\r
299                 /* Wait for a GPIO interrupt to wake this task. */\r
300                 while( xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ) != pdPASS );\r
301 \r
302                 /* Start the Tx of the message on the UART. */\r
303                 UARTIntDisable( UART0_BASE, UART_INT_TX );\r
304                 {\r
305                         pcNextChar = cMessage;\r
306 \r
307                         /* Send the first character. */\r
308                         if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )\r
309                         {\r
310                                 HWREG( UART0_BASE + UART_O_DR ) = *pcNextChar;\r
311                         }\r
312 \r
313                         pcNextChar++;\r
314                 }\r
315                 UARTIntEnable(UART0_BASE, UART_INT_TX);\r
316 \r
317                 /* Queue a message for the print task to display on the LCD. */\r
318                 xQueueSend( xPrintQueue, &pcInterruptMessage, portMAX_DELAY );\r
319 \r
320                 /* Make sure we don't process bounces. */\r
321                 vTaskDelay( mainDEBOUNCE_DELAY );\r
322                 xSemaphoreTake( xButtonSemaphore, mainNO_DELAY );\r
323         }\r
324 }\r
325 \r
326 /*-----------------------------------------------------------*/\r
327 \r
328 void vUART_ISR(void)\r
329 {\r
330 unsigned portLONG ulStatus;\r
331 \r
332         /* What caused the interrupt. */\r
333         ulStatus = UARTIntStatus( UART0_BASE, pdTRUE );\r
334 \r
335         /* Clear the interrupt. */\r
336         UARTIntClear( UART0_BASE, ulStatus );\r
337 \r
338         /* Was a Tx interrupt pending? */\r
339         if( ulStatus & UART_INT_TX )\r
340         {\r
341                 /* Send the next character in the string.  We are not using the FIFO. */\r
342                 if( *pcNextChar != 0 )\r
343                 {\r
344                         if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )\r
345                         {\r
346                                 HWREG( UART0_BASE + UART_O_DR ) = *pcNextChar;\r
347                         }\r
348                         pcNextChar++;\r
349                 }\r
350         }\r
351 }\r
352 /*-----------------------------------------------------------*/\r
353 \r
354 void vGPIO_ISR( void )\r
355 {\r
356 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
357 \r
358         /* Clear the interrupt. */\r
359         GPIOPinIntClear(GPIO_PORTC_BASE, mainPUSH_BUTTON);\r
360 \r
361         /* Wake the button handler task. */\r
362         xSemaphoreGiveFromISR( xButtonSemaphore, &xHigherPriorityTaskWoken );\r
363 \r
364         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
365 }\r
366 /*-----------------------------------------------------------*/\r
367 \r
368 static void vPrintTask( void *pvParameters )\r
369 {\r
370 portCHAR *pcMessage;\r
371 unsigned portBASE_TYPE uxLine = 0, uxRow = 0;\r
372 \r
373         for( ;; )\r
374         {\r
375                 /* Wait for a message to arrive. */\r
376                 xQueueReceive( xPrintQueue, &pcMessage, portMAX_DELAY );\r
377 \r
378                 /* Write the message to the LCD. */\r
379                 uxRow++;\r
380                 uxLine++;\r
381                 OSRAMClear();\r
382                 OSRAMStringDraw( pcMessage, uxLine & 0x3f, uxRow & 0x01);\r
383         }\r
384 }\r
385 \r