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