]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_LM3S811_GCC/main.c
Update version numbers to V7.4.1.
[freertos] / FreeRTOS / Demo / CORTEX_LM3S811_GCC / main.c
1 /*\r
2     FreeRTOS V7.4.1 - Copyright (C) 2013 Real Time Engineers Ltd.\r
3 \r
4     FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME.  PLEASE VISIT\r
5     http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     ***************************************************************************\r
8      *                                                                       *\r
9      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
10      *    Complete, revised, and edited pdf reference manuals are also       *\r
11      *    available.                                                         *\r
12      *                                                                       *\r
13      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
14      *    ensuring you get running as quickly as possible and with an        *\r
15      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
16      *    the FreeRTOS project to continue with its mission of providing     *\r
17      *    professional grade, cross platform, de facto standard solutions    *\r
18      *    for microcontrollers - completely free of charge!                  *\r
19      *                                                                       *\r
20      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
21      *                                                                       *\r
22      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
23      *                                                                       *\r
24     ***************************************************************************\r
25 \r
26 \r
27     This file is part of the FreeRTOS distribution.\r
28 \r
29     FreeRTOS is free software; you can redistribute it and/or modify it under\r
30     the terms of the GNU General Public License (version 2) as published by the\r
31     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
32 \r
33     >>>>>>NOTE<<<<<< The modification to the GPL is included to allow you to\r
34     distribute a combined work that includes FreeRTOS without being obliged to\r
35     provide the source code for proprietary components outside of the FreeRTOS\r
36     kernel.\r
37 \r
38     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
39     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
40     FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\r
41     details. You should have received a copy of the GNU General Public License\r
42     and the FreeRTOS license exception along with FreeRTOS; if not it can be\r
43     viewed here: http://www.freertos.org/a00114.html and also obtained by\r
44     writing to Real Time Engineers Ltd., contact details for whom are available\r
45     on the FreeRTOS WEB site.\r
46 \r
47     1 tab == 4 spaces!\r
48 \r
49     ***************************************************************************\r
50      *                                                                       *\r
51      *    Having a problem?  Start by reading the FAQ "My application does   *\r
52      *    not run, what could be wrong?"                                     *\r
53      *                                                                       *\r
54      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
55      *                                                                       *\r
56     ***************************************************************************\r
57 \r
58 \r
59     http://www.FreeRTOS.org - Documentation, books, training, latest versions, \r
60     license and Real Time Engineers Ltd. contact details.\r
61 \r
62     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
63     including FreeRTOS+Trace - an indispensable productivity tool, and our new\r
64     fully thread aware and reentrant UDP/IP stack.\r
65 \r
66     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High \r
67     Integrity Systems, who sell the code with commercial support, \r
68     indemnification and middleware, under the OpenRTOS brand.\r
69     \r
70     http://www.SafeRTOS.com - High Integrity Systems also provide a safety \r
71     engineered and independently SIL3 certified version for use in safety and \r
72     mission critical applications that require provable dependability.\r
73 */\r
74 \r
75 \r
76 /*\r
77  * This project contains an application demonstrating the use of the\r
78  * FreeRTOS.org mini real time scheduler on the Luminary Micro LM3S811 Eval\r
79  * board.  See http://www.FreeRTOS.org for more information.\r
80  *\r
81  * main() simply sets up the hardware, creates all the demo application tasks,\r
82  * then starts the scheduler.  http://www.freertos.org/a00102.html provides\r
83  * more information on the standard demo tasks.\r
84  *\r
85  * In addition to a subset of the standard demo application tasks, main.c also\r
86  * defines the following tasks:\r
87  *\r
88  * + A 'Print' task.  The print task is the only task permitted to access the\r
89  * LCD - thus ensuring mutual exclusion and consistent access to the resource.\r
90  * Other tasks do not access the LCD directly, but instead send the text they\r
91  * wish to display to the print task.  The print task spends most of its time\r
92  * blocked - only waking when a message is queued for display.\r
93  *\r
94  * + A 'Button handler' task.  The eval board contains a user push button that\r
95  * is configured to generate interrupts.  The interrupt handler uses a\r
96  * semaphore to wake the button handler task - demonstrating how the priority\r
97  * mechanism can be used to defer interrupt processing to the task level.  The\r
98  * button handler task sends a message both to the LCD (via the print task) and\r
99  * the UART where it can be viewed using a dumb terminal (via the UART to USB\r
100  * converter on the eval board).  NOTES:  The dumb terminal must be closed in\r
101  * order to reflash the microcontroller.  A very basic interrupt driven UART\r
102  * driver is used that does not use the FIFO.  19200 baud is used.\r
103  *\r
104  * + A 'check' task.  The check task only executes every five seconds but has a\r
105  * high priority so is guaranteed to get processor time.  Its function is to\r
106  * check that all the other tasks are still operational and that no errors have\r
107  * been detected at any time.  If no errors have every been detected 'PASS' is\r
108  * written to the display (via the print task) - if an error has ever been\r
109  * detected the message is changed to 'FAIL'.  The position of the message is\r
110  * changed for each write.\r
111  */\r
112 \r
113 \r
114 \r
115 /* Environment includes. */\r
116 #include "DriverLib.h"\r
117 \r
118 /* Scheduler includes. */\r
119 #include "FreeRTOS.h"\r
120 #include "task.h"\r
121 #include "queue.h"\r
122 #include "semphr.h"\r
123 \r
124 /* Demo app includes. */\r
125 #include "integer.h"\r
126 #include "PollQ.h"\r
127 #include "semtest.h"\r
128 #include "BlockQ.h"\r
129 \r
130 /* Delay between cycles of the 'check' task. */\r
131 #define mainCHECK_DELAY                                         ( ( portTickType ) 5000 / portTICK_RATE_MS )\r
132 \r
133 /* UART configuration - note this does not use the FIFO so is not very\r
134 efficient. */\r
135 #define mainBAUD_RATE                           ( 19200 )\r
136 #define mainFIFO_SET                            ( 0x10 )\r
137 \r
138 /* Demo task priorities. */\r
139 #define mainQUEUE_POLL_PRIORITY         ( tskIDLE_PRIORITY + 2 )\r
140 #define mainCHECK_TASK_PRIORITY         ( tskIDLE_PRIORITY + 3 )\r
141 #define mainSEM_TEST_PRIORITY           ( tskIDLE_PRIORITY + 1 )\r
142 #define mainBLOCK_Q_PRIORITY            ( tskIDLE_PRIORITY + 2 )\r
143 \r
144 /* Demo board specifics. */\r
145 #define mainPUSH_BUTTON             GPIO_PIN_4\r
146 \r
147 /* Misc. */\r
148 #define mainQUEUE_SIZE                          ( 3 )\r
149 #define mainDEBOUNCE_DELAY                      ( ( portTickType ) 150 / portTICK_RATE_MS )\r
150 #define mainNO_DELAY                            ( ( portTickType ) 0 )\r
151 /*\r
152  * Configure the processor and peripherals for this demo.\r
153  */\r
154 static void prvSetupHardware( void );\r
155 \r
156 /*\r
157  * The 'check' task, as described at the top of this file.\r
158  */\r
159 static void vCheckTask( void *pvParameters );\r
160 \r
161 /*\r
162  * The task that is woken by the ISR that processes GPIO interrupts originating\r
163  * from the push button.\r
164  */\r
165 static void vButtonHandlerTask( void *pvParameters );\r
166 \r
167 /*\r
168  * The task that controls access to the LCD.\r
169  */\r
170 static void vPrintTask( void *pvParameter );\r
171 \r
172 /* String that is transmitted on the UART. */\r
173 static portCHAR *cMessage = "Task woken by button interrupt! --- ";\r
174 static volatile portCHAR *pcNextChar;\r
175 \r
176 /* The semaphore used to wake the button handler task from within the GPIO\r
177 interrupt handler. */\r
178 xSemaphoreHandle xButtonSemaphore;\r
179 \r
180 /* The queue used to send strings to the print task for display on the LCD. */\r
181 xQueueHandle xPrintQueue;\r
182 \r
183 /*-----------------------------------------------------------*/\r
184 \r
185 int main( void )\r
186 {\r
187         /* Configure the clocks, UART and GPIO. */\r
188         prvSetupHardware();\r
189 \r
190         /* Create the semaphore used to wake the button handler task from the GPIO\r
191         ISR. */\r
192         vSemaphoreCreateBinary( xButtonSemaphore );\r
193         xSemaphoreTake( xButtonSemaphore, 0 );\r
194 \r
195         /* Create the queue used to pass message to vPrintTask. */\r
196         xPrintQueue = xQueueCreate( mainQUEUE_SIZE, sizeof( portCHAR * ) );\r
197 \r
198         /* Start the standard demo tasks. */\r
199         vStartIntegerMathTasks( tskIDLE_PRIORITY );\r
200         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
201         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
202         vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
203 \r
204         /* Start the tasks defined within the file. */\r
205         xTaskCreate( vCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
206         xTaskCreate( vButtonHandlerTask, "Status", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY + 1, NULL );\r
207         xTaskCreate( vPrintTask, "Print", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL );\r
208 \r
209         /* Start the scheduler. */\r
210         vTaskStartScheduler();\r
211 \r
212         /* Will only get here if there was insufficient heap to start the\r
213         scheduler. */\r
214 \r
215         return 0;\r
216 }\r
217 /*-----------------------------------------------------------*/\r
218 \r
219 static void vCheckTask( void *pvParameters )\r
220 {\r
221 portBASE_TYPE xErrorOccurred = pdFALSE;\r
222 portTickType xLastExecutionTime;\r
223 const portCHAR *pcPassMessage = "PASS";\r
224 const portCHAR *pcFailMessage = "FAIL";\r
225 \r
226         /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()\r
227         works correctly. */\r
228         xLastExecutionTime = xTaskGetTickCount();\r
229 \r
230         for( ;; )\r
231         {\r
232                 /* Perform this check every mainCHECK_DELAY milliseconds. */\r
233                 vTaskDelayUntil( &xLastExecutionTime, mainCHECK_DELAY );\r
234 \r
235                 /* Has an error been found in any task? */\r
236 \r
237                 if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
238                 {\r
239                         xErrorOccurred = pdTRUE;\r
240                 }\r
241         \r
242                 if( xArePollingQueuesStillRunning() != pdTRUE )\r
243                 {\r
244                         xErrorOccurred = pdTRUE;\r
245                 }\r
246         \r
247                 if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
248                 {\r
249                         xErrorOccurred = pdTRUE;\r
250                 }\r
251 \r
252                 if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
253                 {\r
254                         xErrorOccurred = pdTRUE;\r
255                 }\r
256 \r
257                 /* Send either a pass or fail message.  If an error is found it is\r
258                 never cleared again.  We do not write directly to the LCD, but instead\r
259                 queue a message for display by the print task. */\r
260                 if( xErrorOccurred == pdTRUE )\r
261                 {\r
262                         xQueueSend( xPrintQueue, &pcFailMessage, portMAX_DELAY );\r
263                 }\r
264                 else\r
265                 {\r
266                         xQueueSend( xPrintQueue, &pcPassMessage, portMAX_DELAY );\r
267                 }\r
268         }\r
269 }\r
270 /*-----------------------------------------------------------*/\r
271 \r
272 static void prvSetupHardware( void )\r
273 {\r
274         /* Setup the PLL. */\r
275         SysCtlClockSet( SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_6MHZ );\r
276 \r
277         /* Setup the push button. */\r
278         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);\r
279     GPIODirModeSet(GPIO_PORTC_BASE, mainPUSH_BUTTON, GPIO_DIR_MODE_IN);\r
280         GPIOIntTypeSet( GPIO_PORTC_BASE, mainPUSH_BUTTON,GPIO_FALLING_EDGE );\r
281         IntPrioritySet( INT_GPIOC, configKERNEL_INTERRUPT_PRIORITY );\r
282         GPIOPinIntEnable( GPIO_PORTC_BASE, mainPUSH_BUTTON );\r
283         IntEnable( INT_GPIOC );\r
284 \r
285 \r
286 \r
287         /* Enable the UART.  */\r
288         SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);\r
289         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);\r
290 \r
291         /* Set GPIO A0 and A1 as peripheral function.  They are used to output the\r
292         UART signals. */\r
293         GPIODirModeSet( GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_DIR_MODE_HW );\r
294 \r
295         /* Configure the UART for 8-N-1 operation. */\r
296         UARTConfigSet( UART0_BASE, mainBAUD_RATE, UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE );\r
297 \r
298         /* We don't want to use the fifo.  This is for test purposes to generate\r
299         as many interrupts as possible. */\r
300         HWREG( UART0_BASE + UART_O_LCR_H ) &= ~mainFIFO_SET;\r
301 \r
302         /* Enable Tx interrupts. */\r
303         HWREG( UART0_BASE + UART_O_IM ) |= UART_INT_TX;\r
304         IntPrioritySet( INT_UART0, configKERNEL_INTERRUPT_PRIORITY );\r
305         IntEnable( INT_UART0 );\r
306 \r
307 \r
308         /* Initialise the LCD> */\r
309     OSRAMInit( false );\r
310     OSRAMStringDraw("www.FreeRTOS.org", 0, 0);\r
311         OSRAMStringDraw("LM3S811 demo", 16, 1);\r
312 }\r
313 /*-----------------------------------------------------------*/\r
314 \r
315 static void vButtonHandlerTask( void *pvParameters )\r
316 {\r
317 const portCHAR *pcInterruptMessage = "Int";\r
318 \r
319         for( ;; )\r
320         {\r
321                 /* Wait for a GPIO interrupt to wake this task. */\r
322                 while( xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ) != pdPASS );\r
323 \r
324                 /* Start the Tx of the message on the UART. */\r
325                 UARTIntDisable( UART0_BASE, UART_INT_TX );\r
326                 {\r
327                         pcNextChar = cMessage;\r
328 \r
329                         /* Send the first character. */\r
330                         if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )\r
331                         {\r
332                                 HWREG( UART0_BASE + UART_O_DR ) = *pcNextChar;\r
333                         }\r
334 \r
335                         pcNextChar++;\r
336                 }\r
337                 UARTIntEnable(UART0_BASE, UART_INT_TX);\r
338 \r
339                 /* Queue a message for the print task to display on the LCD. */\r
340                 xQueueSend( xPrintQueue, &pcInterruptMessage, portMAX_DELAY );\r
341 \r
342                 /* Make sure we don't process bounces. */\r
343                 vTaskDelay( mainDEBOUNCE_DELAY );\r
344                 xSemaphoreTake( xButtonSemaphore, mainNO_DELAY );\r
345         }\r
346 }\r
347 \r
348 /*-----------------------------------------------------------*/\r
349 \r
350 void vUART_ISR(void)\r
351 {\r
352 unsigned portLONG ulStatus;\r
353 \r
354         /* What caused the interrupt. */\r
355         ulStatus = UARTIntStatus( UART0_BASE, pdTRUE );\r
356 \r
357         /* Clear the interrupt. */\r
358         UARTIntClear( UART0_BASE, ulStatus );\r
359 \r
360         /* Was a Tx interrupt pending? */\r
361         if( ulStatus & UART_INT_TX )\r
362         {\r
363                 /* Send the next character in the string.  We are not using the FIFO. */\r
364                 if( *pcNextChar != 0 )\r
365                 {\r
366                         if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )\r
367                         {\r
368                                 HWREG( UART0_BASE + UART_O_DR ) = *pcNextChar;\r
369                         }\r
370                         pcNextChar++;\r
371                 }\r
372         }\r
373 }\r
374 /*-----------------------------------------------------------*/\r
375 \r
376 void vGPIO_ISR( void )\r
377 {\r
378 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
379 \r
380         /* Clear the interrupt. */\r
381         GPIOPinIntClear(GPIO_PORTC_BASE, mainPUSH_BUTTON);\r
382 \r
383         /* Wake the button handler task. */\r
384         xSemaphoreGiveFromISR( xButtonSemaphore, &xHigherPriorityTaskWoken );\r
385 \r
386         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
387 }\r
388 /*-----------------------------------------------------------*/\r
389 \r
390 static void vPrintTask( void *pvParameters )\r
391 {\r
392 portCHAR *pcMessage;\r
393 unsigned portBASE_TYPE uxLine = 0, uxRow = 0;\r
394 \r
395         for( ;; )\r
396         {\r
397                 /* Wait for a message to arrive. */\r
398                 xQueueReceive( xPrintQueue, &pcMessage, portMAX_DELAY );\r
399 \r
400                 /* Write the message to the LCD. */\r
401                 uxRow++;\r
402                 uxLine++;\r
403                 OSRAMClear();\r
404                 OSRAMStringDraw( pcMessage, uxLine & 0x3f, uxRow & 0x01);\r
405         }\r
406 }\r
407 \r