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