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