]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_LM3S811_IAR/main.c
Update license information text files for the CLI, TCP and UDP products to be correct...
[freertos] / FreeRTOS / Demo / CORTEX_LM3S811_IAR / 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 /*-----------------------------------------------------------*/\r
138 \r
139 int main( void )\r
140 {\r
141         /* Configure the clocks, UART and GPIO. */\r
142         prvSetupHardware();\r
143 \r
144         /* Create the semaphore used to wake the button handler task from the GPIO\r
145         ISR. */\r
146         vSemaphoreCreateBinary( xButtonSemaphore );\r
147         xSemaphoreTake( xButtonSemaphore, 0 );\r
148 \r
149         /* Create the queue used to pass message to vPrintTask. */\r
150         xPrintQueue = xQueueCreate( mainQUEUE_SIZE, sizeof( char * ) );\r
151 \r
152         /* Start the standard demo tasks. */\r
153         vStartIntegerMathTasks( tskIDLE_PRIORITY );\r
154         vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
155         vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
156         vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
157 \r
158         /* Start the tasks defined within the file. */\r
159         xTaskCreate( vCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
160         xTaskCreate( vButtonHandlerTask, "Status", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY + 1, NULL );\r
161         xTaskCreate( vPrintTask, "Print", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL );\r
162 \r
163         /* Start the scheduler. */\r
164         vTaskStartScheduler();\r
165 \r
166         /* Will only get here if there was insufficient heap to start the\r
167         scheduler. */\r
168 \r
169         return 0;\r
170 }\r
171 /*-----------------------------------------------------------*/\r
172 \r
173 static void vCheckTask( void *pvParameters )\r
174 {\r
175 portBASE_TYPE xErrorOccurred = pdFALSE;\r
176 TickType_t xLastExecutionTime;\r
177 const char *pcPassMessage = "PASS";\r
178 const char *pcFailMessage = "FAIL";\r
179 \r
180         /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()\r
181         works correctly. */\r
182         xLastExecutionTime = xTaskGetTickCount();\r
183 \r
184         for( ;; )\r
185         {\r
186                 /* Perform this check every mainCHECK_DELAY milliseconds. */\r
187                 vTaskDelayUntil( &xLastExecutionTime, mainCHECK_DELAY );\r
188 \r
189                 /* Has an error been found in any task? */\r
190 \r
191                 if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
192                 {\r
193                         xErrorOccurred = pdTRUE;\r
194                 }\r
195         \r
196                 if( xArePollingQueuesStillRunning() != pdTRUE )\r
197                 {\r
198                         xErrorOccurred = pdTRUE;\r
199                 }\r
200         \r
201                 if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
202                 {\r
203                         xErrorOccurred = pdTRUE;\r
204                 }\r
205 \r
206                 if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
207                 {\r
208                         xErrorOccurred = pdTRUE;\r
209                 }\r
210 \r
211                 /* Send either a pass or fail message.  If an error is found it is\r
212                 never cleared again.  We do not write directly to the LCD, but instead\r
213                 queue a message for display by the print task. */\r
214                 if( xErrorOccurred == pdTRUE )\r
215                 {\r
216                         xQueueSend( xPrintQueue, &pcFailMessage, portMAX_DELAY );\r
217                 }\r
218                 else\r
219                 {\r
220                         xQueueSend( xPrintQueue, &pcPassMessage, portMAX_DELAY );\r
221                 }\r
222         }\r
223 }\r
224 /*-----------------------------------------------------------*/\r
225 \r
226 static void prvSetupHardware( void )\r
227 {\r
228         /* Setup the PLL. */\r
229         SysCtlClockSet( SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_6MHZ );\r
230 \r
231         /* Setup the push button. */\r
232         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);\r
233     GPIODirModeSet(GPIO_PORTC_BASE, mainPUSH_BUTTON, GPIO_DIR_MODE_IN);\r
234         GPIOIntTypeSet( GPIO_PORTC_BASE, mainPUSH_BUTTON,GPIO_FALLING_EDGE );\r
235         IntPrioritySet( INT_GPIOC, configKERNEL_INTERRUPT_PRIORITY );\r
236         GPIOPinIntEnable( GPIO_PORTC_BASE, mainPUSH_BUTTON );\r
237         IntEnable( INT_GPIOC );\r
238 \r
239 \r
240 \r
241         /* Enable the UART.  */\r
242         SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);\r
243         SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);\r
244 \r
245         /* Set GPIO A0 and A1 as peripheral function.  They are used to output the\r
246         UART signals. */\r
247         GPIODirModeSet( GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_DIR_MODE_HW );\r
248 \r
249         /* Configure the UART for 8-N-1 operation. */\r
250         UARTConfigSetExpClk( UART0_BASE, SysCtlClockGet(), mainBAUD_RATE, UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE );\r
251 \r
252         /* We don't want to use the fifo.  This is for test purposes to generate\r
253         as many interrupts as possible. */\r
254         HWREG( UART0_BASE + UART_O_LCR_H ) &= ~mainFIFO_SET;\r
255 \r
256         /* Enable Tx interrupts. */\r
257         HWREG( UART0_BASE + UART_O_IM ) |= UART_INT_TX;\r
258         IntPrioritySet( INT_UART0, configKERNEL_INTERRUPT_PRIORITY );\r
259         IntEnable( INT_UART0 );\r
260 \r
261 \r
262         /* Initialise the LCD> */\r
263     OSRAMInit( false );\r
264     OSRAMStringDraw("www.FreeRTOS.org", 0, 0);\r
265         OSRAMStringDraw("LM3S811 demo", 16, 1);\r
266 }\r
267 /*-----------------------------------------------------------*/\r
268 \r
269 static void vButtonHandlerTask( void *pvParameters )\r
270 {\r
271 const char *pcInterruptMessage = "Int";\r
272 \r
273         for( ;; )\r
274         {\r
275                 /* Wait for a GPIO interrupt to wake this task. */\r
276                 while( xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ) != pdPASS );\r
277 \r
278                 /* Start the Tx of the message on the UART. */\r
279                 UARTIntDisable( UART0_BASE, UART_INT_TX );\r
280                 {\r
281                         pcNextChar = cMessage;\r
282 \r
283                         /* Send the first character. */\r
284                         if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )\r
285                         {\r
286                                 HWREG( UART0_BASE + UART_O_DR ) = *pcNextChar;\r
287                         }\r
288 \r
289                         pcNextChar++;\r
290                 }\r
291                 UARTIntEnable(UART0_BASE, UART_INT_TX);\r
292 \r
293                 /* Queue a message for the print task to display on the LCD. */\r
294                 xQueueSend( xPrintQueue, &pcInterruptMessage, portMAX_DELAY );\r
295 \r
296                 /* Make sure we don't process bounces. */\r
297                 vTaskDelay( mainDEBOUNCE_DELAY );\r
298                 xSemaphoreTake( xButtonSemaphore, mainNO_DELAY );\r
299         }\r
300 }\r
301 \r
302 /*-----------------------------------------------------------*/\r
303 \r
304 void vUART_ISR(void)\r
305 {\r
306 unsigned long ulStatus;\r
307 \r
308         /* What caused the interrupt. */\r
309         ulStatus = UARTIntStatus( UART0_BASE, pdTRUE );\r
310 \r
311         /* Clear the interrupt. */\r
312         UARTIntClear( UART0_BASE, ulStatus );\r
313 \r
314         /* Was a Tx interrupt pending? */\r
315         if( ulStatus & UART_INT_TX )\r
316         {\r
317                 /* Send the next character in the string.  We are not using the FIFO. */\r
318                 if( *pcNextChar != NULL )\r
319                 {\r
320                         if( !( HWREG( UART0_BASE + UART_O_FR ) & UART_FR_TXFF ) )\r
321                         {\r
322                                 HWREG( UART0_BASE + UART_O_DR ) = *pcNextChar;\r
323                         }\r
324                         pcNextChar++;\r
325                 }\r
326         }\r
327 }\r
328 /*-----------------------------------------------------------*/\r
329 \r
330 void vGPIO_ISR( void )\r
331 {\r
332 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
333 \r
334         /* Clear the interrupt. */\r
335         GPIOPinIntClear(GPIO_PORTC_BASE, mainPUSH_BUTTON);\r
336 \r
337         /* Wake the button handler task. */\r
338         xSemaphoreGiveFromISR( xButtonSemaphore, &xHigherPriorityTaskWoken );\r
339         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
340 }\r
341 /*-----------------------------------------------------------*/\r
342 \r
343 static void vPrintTask( void *pvParameters )\r
344 {\r
345 char *pcMessage;\r
346 unsigned portBASE_TYPE uxLine = 0, uxRow = 0;\r
347 \r
348         for( ;; )\r
349         {\r
350                 /* Wait for a message to arrive. */\r
351                 xQueueReceive( xPrintQueue, &pcMessage, portMAX_DELAY );\r
352 \r
353                 /* Write the message to the LCD. */\r
354                 uxRow++;\r
355                 uxLine++;\r
356                 OSRAMClear();\r
357                 OSRAMStringDraw( pcMessage, uxLine & 0x3f, uxRow & 0x01);\r
358         }\r
359 }\r
360 \r