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