]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_LM3S811_KEIL/main.c
Update license information text files for the CLI, TCP and UDP products to be correct...
[freertos] / FreeRTOS / Demo / CORTEX_LM3S811_KEIL / main.c
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29 \r
30 /*\r
31  * This project contains an application demonstrating the use of the \r
32  * FreeRTOS.org mini real time scheduler on the Luminary Micro LM3S811 Eval\r
33  * board.  See http://www.FreeRTOS.org for more information.\r
34  *\r
35  * main() simply sets up the hardware, creates all the demo application tasks, \r
36  * then starts the scheduler.  http://www.freertos.org/a00102.html provides\r
37  * more information on the standard demo tasks. \r
38  *\r
39  * In addition to a subset of the standard demo application tasks, main.c also\r
40  * defines the following tasks: \r
41  *\r
42  * + A 'Print' task.  The print task is the only task permitted to access the\r
43  * LCD - thus ensuring mutual exclusion and consistent access to the resource.\r
44  * Other tasks do not access the LCD directly, but instead send the text they\r
45  * wish to display to the print task.  The print task spends most of its time\r
46  * blocked - only waking when a message is queued for display.\r
47  *\r
48  * + A 'Button handler' task.  The eval board contains a user push button that\r
49  * is configured to generate interrupts.  The interrupt handler uses a \r
50  * semaphore to wake the button handler task - demonstrating how the priority \r
51  * mechanism can be used to defer interrupt processing to the task level.  The\r
52  * button handler task sends a message both to the LCD (via the print task) and\r
53  * the UART where it can be viewed using a dumb terminal (via the UART to USB\r
54  * converter on the eval board).  NOTES:  The dumb terminal must be closed in \r
55  * order to reflash the microcontroller.  A very basic interrupt driven UART\r
56  * driver is used that does not use the FIFO.  19200 baud is used.\r
57  *\r
58  * + A 'check' task.  The check task only executes every five seconds but has a\r
59  * high priority so is guaranteed to get processor time.  Its function is to\r
60  * check that all the other tasks are still operational and that no errors have\r
61  * been detected at any time.  If no errors have every been detected 'PASS' is\r
62  * written to the display (via the print task) - if an error has ever been\r
63  * detected the message is changed to 'FAIL'.  The position of the message is\r
64  * changed for each write.\r
65  */\r
66 \r
67 \r
68 \r
69 /* Environment includes. */\r
70 #include "DriverLib.h"\r
71 \r
72 /* Scheduler includes. */\r
73 #include "FreeRTOS.h"\r
74 #include "task.h"\r
75 #include "queue.h"\r
76 #include "semphr.h"\r
77 \r
78 /* Demo app includes. */\r
79 #include "integer.h"\r
80 #include "PollQ.h"\r
81 #include "semtest.h"\r
82 #include "BlockQ.h"\r
83 \r
84 /* Delay between cycles of the 'check' task. */\r
85 #define mainCHECK_DELAY                                         ( ( TickType_t ) 5000 / portTICK_PERIOD_MS )\r
86 \r
87 /* UART configuration - note this does not use the FIFO so is not very \r
88 efficient. */\r
89 #define mainBAUD_RATE                           ( 19200 )\r
90 #define mainFIFO_SET                            ( 0x10 )\r
91 \r
92 /* Demo task priorities. */\r
93 #define mainQUEUE_POLL_PRIORITY         ( tskIDLE_PRIORITY + 2 )\r
94 #define mainCHECK_TASK_PRIORITY         ( tskIDLE_PRIORITY + 3 )\r
95 #define mainSEM_TEST_PRIORITY           ( tskIDLE_PRIORITY + 1 )\r
96 #define mainBLOCK_Q_PRIORITY            ( tskIDLE_PRIORITY + 2 )\r
97 \r
98 /* Demo board specifics. */\r
99 #define mainPUSH_BUTTON             GPIO_PIN_4\r
100 \r
101 /* Misc. */\r
102 #define mainQUEUE_SIZE                          ( 3 )\r
103 #define mainDEBOUNCE_DELAY                      ( ( TickType_t ) 150 / portTICK_PERIOD_MS )\r
104 #define mainNO_DELAY                            ( ( TickType_t ) 0 )\r
105 /*\r
106  * Configure the processor and peripherals for this demo. \r
107  */\r
108 static void prvSetupHardware( void );\r
109 \r
110 /*\r
111  * The 'check' task, as described at the top of this file.\r
112  */\r
113 static void vCheckTask( void *pvParameters );\r
114 \r
115 /*\r
116  * The task that is woken by the ISR that processes GPIO interrupts originating\r
117  * from the push button.\r
118  */\r
119 static void vButtonHandlerTask( void *pvParameters );\r
120 \r
121 /*\r
122  * The task that controls access to the LCD.\r
123  */\r
124 static void vPrintTask( void *pvParameter );\r
125 \r
126 /* String that is transmitted on the UART. */\r
127 static char *cMessage = "Task woken by button interrupt! --- ";\r
128 static volatile char *pcNextChar;\r
129 \r
130 /* The semaphore used to wake the button handler task from within the GPIO\r
131 interrupt handler. */\r
132 SemaphoreHandle_t xButtonSemaphore;\r
133 \r
134 /* The queue used to send strings to the print task for display on the LCD. */\r
135 QueueHandle_t xPrintQueue;\r
136 \r
137 /* Newer library version. */\r
138 extern void UARTConfigSetExpClk(unsigned long ulBase, unsigned long ulUARTClk, unsigned long ulBaud, unsigned long ulConfig);\r
139 /*-----------------------------------------------------------*/\r
140 \r
141 int main( void )\r
142 {\r
143         /* Configure the clocks, UART and GPIO. */\r
144         prvSetupHardware();\r
145 \r
146         /* Create the semaphore used to wake the button handler task from the GPIO\r
147         ISR. */\r
148         vSemaphoreCreateBinary( xButtonSemaphore );\r
149         xSemaphoreTake( xButtonSemaphore, 0 );\r
150 \r
151         /* Create the queue used to pass message to vPrintTask. */\r
152         xPrintQueue = xQueueCreate( mainQUEUE_SIZE, sizeof( char * ) );\r
153 \r
154         /* Start the standard demo tasks. */\r
155         vStartIntegerMathTasks( tskIDLE_PRIORITY );\r
156         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
157         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
158         vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
159 \r
160         /* Start the tasks defined within the file. */\r
161         xTaskCreate( vCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
162         xTaskCreate( vButtonHandlerTask, "Status", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY + 1, NULL );\r
163         xTaskCreate( vPrintTask, "Print", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL );\r
164 \r
165         /* Start the scheduler. */\r
166         vTaskStartScheduler();\r
167 \r
168         /* Will only get here if there was insufficient heap to start the \r
169         scheduler. */\r
170 \r
171         return 0;\r
172 }\r
173 /*-----------------------------------------------------------*/\r
174 \r
175 static void vCheckTask( void *pvParameters )\r
176 {\r
177 portBASE_TYPE xErrorOccurred = pdFALSE;\r
178 TickType_t xLastExecutionTime;\r
179 const char *pcPassMessage = "PASS";\r
180 const char *pcFailMessage = "FAIL";\r
181 \r
182         /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()\r
183         works correctly. */\r
184         xLastExecutionTime = xTaskGetTickCount();\r
185 \r
186         for( ;; )\r
187         {\r
188                 /* Perform this check every mainCHECK_DELAY milliseconds. */\r
189                 vTaskDelayUntil( &xLastExecutionTime, mainCHECK_DELAY );\r
190 \r
191                 /* Has an error been found in any task? */\r
192 \r
193                 if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
194                 {\r
195                         xErrorOccurred = pdTRUE;\r
196                 }\r
197         \r
198                 if( xArePollingQueuesStillRunning() != pdTRUE )\r
199                 {\r
200                         xErrorOccurred = pdTRUE;\r
201                 }\r
202         \r
203                 if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
204                 {\r
205                         xErrorOccurred = pdTRUE;\r
206                 }\r
207 \r
208                 if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
209                 {\r
210                         xErrorOccurred = pdTRUE;\r
211                 }\r
212 \r
213                 /* Send either a pass or fail message.  If an error is found it is\r
214                 never cleared again.  We do not write directly to the LCD, but instead\r
215                 queue a message for display by the print task. */\r
216                 if( xErrorOccurred == pdTRUE )\r
217                 {\r
218                         xQueueSend( xPrintQueue, &pcFailMessage, portMAX_DELAY );\r
219                 }\r
220                 else\r
221                 {\r
222                         xQueueSend( xPrintQueue, &pcPassMessage, portMAX_DELAY );\r
223                 }\r
224         }\r
225 }\r
226 /*-----------------------------------------------------------*/\r
227 \r
228 static void prvSetupHardware( void )\r
229 {\r
230         /* Setup the PLL. */\r
231         SysCtlClockSet( SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_6MHZ );\r
232 \r
233         /* Setup the push button. */\r
234         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);\r
235     GPIODirModeSet(GPIO_PORTC_BASE, mainPUSH_BUTTON, GPIO_DIR_MODE_IN);\r
236         GPIOIntTypeSet( GPIO_PORTC_BASE, mainPUSH_BUTTON,GPIO_FALLING_EDGE );\r
237         IntPrioritySet( INT_GPIOC, configKERNEL_INTERRUPT_PRIORITY );\r
238         GPIOPinIntEnable( GPIO_PORTC_BASE, mainPUSH_BUTTON );\r
239         IntEnable( INT_GPIOC );\r
240 \r
241 \r
242 \r
243         /* Enable the UART.  */\r
244         SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);\r
245         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);\r
246 \r
247         /* Set GPIO A0 and A1 as peripheral function.  They are used to output the\r
248         UART signals. */\r
249         GPIODirModeSet( GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_DIR_MODE_HW );\r
250 \r
251         /* Configure the UART for 8-N-1 operation. */\r
252         UARTConfigSetExpClk( UART0_BASE, SysCtlClockGet(), mainBAUD_RATE, UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE );\r
253 \r
254         /* We don't want to use the fifo.  This is for test purposes to generate\r
255         as many interrupts as possible. */\r
256         HWREG( UART0_BASE + UART_O_LCR_H ) &= ~mainFIFO_SET;\r
257 \r
258         /* Enable Tx interrupts. */\r
259         HWREG( UART0_BASE + UART_O_IM ) |= UART_INT_TX;\r
260         IntPrioritySet( INT_UART0, configKERNEL_INTERRUPT_PRIORITY );\r
261         IntEnable( INT_UART0 );\r
262 \r
263 \r
264         /* Initialise the LCD> */\r
265     OSRAMInit( false );\r
266     OSRAMStringDraw("www.FreeRTOS.org", 0, 0);\r
267         OSRAMStringDraw("LM3S811 demo", 16, 1);\r
268 }\r
269 /*-----------------------------------------------------------*/\r
270 \r
271 static void vButtonHandlerTask( void *pvParameters )\r
272 {\r
273 const char *pcInterruptMessage = "Int";\r
274 \r
275         for( ;; )\r
276         {\r
277                 /* Wait for a GPIO interrupt to wake this task. */\r
278                 while( xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ) != pdPASS );\r
279 \r
280                 /* Start the Tx of the message on the UART. */\r
281                 UARTIntDisable( UART0_BASE, UART_INT_TX );\r
282                 {\r
283                         pcNextChar = cMessage;\r
284 \r
285                         /* Send the first character. */\r
286                         if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )\r
287                         {\r
288                                 HWREG( UART0_BASE + UART_O_DR ) = *pcNextChar;\r
289                         }\r
290 \r
291                         pcNextChar++;\r
292                 }\r
293                 UARTIntEnable(UART0_BASE, UART_INT_TX);\r
294 \r
295                 /* Queue a message for the print task to display on the LCD. */\r
296                 xQueueSend( xPrintQueue, &pcInterruptMessage, portMAX_DELAY );\r
297 \r
298                 /* Make sure we don't process bounces. */\r
299                 vTaskDelay( mainDEBOUNCE_DELAY );\r
300                 xSemaphoreTake( xButtonSemaphore, mainNO_DELAY );\r
301         }\r
302 }\r
303 \r
304 /*-----------------------------------------------------------*/\r
305 \r
306 void vUART_ISR(void)\r
307 {\r
308 unsigned long ulStatus;\r
309 \r
310         /* What caused the interrupt. */\r
311         ulStatus = UARTIntStatus( UART0_BASE, pdTRUE );\r
312 \r
313         /* Clear the interrupt. */\r
314         UARTIntClear( UART0_BASE, ulStatus );\r
315 \r
316         /* Was a Tx interrupt pending? */\r
317         if( ulStatus & UART_INT_TX )\r
318         {\r
319                 /* Send the next character in the string.  We are not using the FIFO. */\r
320                 if( *pcNextChar != NULL )\r
321                 {\r
322                         if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )\r
323                         {\r
324                                 HWREG( UART0_BASE + UART_O_DR ) = *pcNextChar;\r
325                         }\r
326                         pcNextChar++;\r
327                 }\r
328         }\r
329 }\r
330 /*-----------------------------------------------------------*/\r
331 \r
332 void vGPIO_ISR( void )\r
333 {\r
334 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
335 \r
336         /* Clear the interrupt. */\r
337         GPIOPinIntClear( GPIO_PORTC_BASE, mainPUSH_BUTTON );\r
338 \r
339         /* Wake the button handler task. */\r
340         xSemaphoreGiveFromISR( xButtonSemaphore, &xHigherPriorityTaskWoken );\r
341         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
342 }\r
343 /*-----------------------------------------------------------*/\r
344 \r
345 static void vPrintTask( void *pvParameters )\r
346 {\r
347 char *pcMessage;\r
348 unsigned portBASE_TYPE uxLine = 0, uxRow = 0;\r
349 \r
350         for( ;; )\r
351         {\r
352                 /* Wait for a message to arrive. */\r
353                 xQueueReceive( xPrintQueue, &pcMessage, portMAX_DELAY );\r
354 \r
355                 /* Write the message to the LCD. */\r
356                 uxRow++;\r
357                 uxLine++;\r
358                 OSRAMClear();\r
359                 OSRAMStringDraw( pcMessage, uxLine & 0x3f, uxRow & 0x01);\r
360         }\r
361 }\r
362 \r