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