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