]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOSDemo/src/main.c
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Demo / MicroBlaze_Kintex7_EthernetLite / RTOSDemo / src / 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  * This project provides three demo applications.  A simple blinky style\r
31  * project, a more comprehensive test and demo application, and an lwIP example.\r
32  * The mainSELECTED_APPLICATION setting (defined in this file) is used to\r
33  * select between the three.  The simply blinky demo is implemented and\r
34  * described in main_blinky.c.  The more comprehensive test and demo application\r
35  * is implemented and described in main_full.c.  The lwIP example is implemented\r
36  * and described in main_lwIP.c.\r
37  *\r
38  * This file implements the code that is not demo specific, including the\r
39  * hardware setup and FreeRTOS hook functions.\r
40  *\r
41  * ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON\r
42  * THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO\r
43  * APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT!\r
44  *\r
45  */\r
46 \r
47 /* Standard includes. */\r
48 #include <stdio.h>\r
49 #include <limits.h>\r
50 \r
51 /* Scheduler include files. */\r
52 #include "FreeRTOS.h"\r
53 #include "task.h"\r
54 \r
55 /* Demo app includes. */\r
56 #include "partest.h"\r
57 \r
58 /* Xilinx includes. */\r
59 #include "xtmrctr.h"\r
60 #include "xil_cache.h"\r
61 \r
62 /* mainSELECTED_APPLICATION is used to select between three demo applications,\r
63  * as described at the top of this file.\r
64  *\r
65  * When mainSELECTED_APPLICATION is set to 0 the simple blinky example will\r
66  * be run.\r
67  *\r
68  * When mainSELECTED_APPLICATION is set to 1 the comprehensive test and demo\r
69  * application will be run.\r
70  *\r
71  * When mainSELECTED_APPLICATION is set to 2 the lwIP example will be run.\r
72  */\r
73 #define mainSELECTED_APPLICATION        0\r
74 \r
75 /*-----------------------------------------------------------*/\r
76 \r
77 /*\r
78  * Configure the hardware as necessary to run this demo.\r
79  */\r
80 static void prvSetupHardware( void );\r
81 \r
82 /*\r
83 * See the comments at the top of this file and above the\r
84 * mainSELECTED_APPLICATION definition.\r
85 */\r
86 #if ( mainSELECTED_APPLICATION == 0 )\r
87         extern void main_blinky( void );\r
88 #elif ( mainSELECTED_APPLICATION == 1 )\r
89         extern void main_full( void );\r
90 #elif ( mainSELECTED_APPLICATION == 2 )\r
91         extern void main_lwIP( void );\r
92 #else\r
93         #error Invalid mainSELECTED_APPLICATION setting.  See the comments at the top of this file and above the mainSELECTED_APPLICATION definition.\r
94 #endif\r
95 \r
96 /* Prototypes for the standard FreeRTOS callback/hook functions implemented\r
97 within this file. */\r
98 void vApplicationMallocFailedHook( void );\r
99 void vApplicationIdleHook( void );\r
100 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );\r
101 void vApplicationTickHook( void );\r
102 \r
103 /* The dual timer is used to generate the RTOS tick interrupt and as a time base\r
104 for the run time stats. */\r
105 static XTmrCtr xTickTimerInstance;\r
106 \r
107 /*-----------------------------------------------------------*/\r
108 \r
109 int main( void )\r
110 {\r
111         /* Configure the hardware ready to run the demo. */\r
112         prvSetupHardware();\r
113 \r
114         /* The mainSELECTED_APPLICATION setting is described at the top\r
115         of this file. */\r
116         #if( mainSELECTED_APPLICATION == 0 )\r
117         {\r
118                 main_blinky();\r
119         }\r
120         #elif( mainSELECTED_APPLICATION == 1 )\r
121         {\r
122                 main_full();\r
123         }\r
124         #else\r
125         {\r
126                 main_lwIP();\r
127         }\r
128         #endif\r
129 \r
130         /* Don't expect to reach here. */\r
131         return 0;\r
132 }\r
133 /*-----------------------------------------------------------*/\r
134 \r
135 static void prvSetupHardware( void )\r
136 {\r
137         microblaze_disable_interrupts();\r
138 \r
139         #if defined( XPAR_MICROBLAZE_USE_ICACHE ) && ( XPAR_MICROBLAZE_USE_ICACHE != 0 )\r
140         {\r
141                 Xil_ICacheInvalidate();\r
142                 Xil_ICacheEnable();\r
143         }\r
144         #endif\r
145 \r
146         #if defined( XPAR_MICROBLAZE_USE_DCACHE ) && ( XPAR_MICROBLAZE_USE_DCACHE != 0 )\r
147         {\r
148                 Xil_DCacheInvalidate();\r
149                 Xil_DCacheEnable();\r
150         }\r
151         #endif\r
152 \r
153         /* Initialise the LEDs.  ParTest is a historic name which used to stand for\r
154         PARallel port TEST. */\r
155         vParTestInitialise();\r
156 }\r
157 /*-----------------------------------------------------------*/\r
158 \r
159 void vApplicationMallocFailedHook( void )\r
160 {\r
161 volatile uint32_t ulDummy = 0;\r
162 \r
163         /* Called if a call to pvPortMalloc() fails because there is insufficient\r
164         free memory available in the FreeRTOS heap.  pvPortMalloc() is called\r
165         internally by FreeRTOS API functions that create tasks, queues, software\r
166         timers, and semaphores.  The size of the FreeRTOS heap is set by the\r
167         configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h.  Force an\r
168         assertion failure. */\r
169         configASSERT( ulDummy != 0 );\r
170 }\r
171 /*-----------------------------------------------------------*/\r
172 \r
173 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )\r
174 {\r
175         ( void ) pcTaskName;\r
176         ( void ) pxTask;\r
177 \r
178         /* Run time stack overflow checking is performed if\r
179         configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.  This hook\r
180         function is called if a stack overflow is detected.  Force an assertion\r
181         failure. */\r
182         configASSERT( ( char * ) pxTask == pcTaskName );\r
183 }\r
184 /*-----------------------------------------------------------*/\r
185 \r
186 void vApplicationIdleHook( void )\r
187 {\r
188         #if( mainSELECTED_APPLICATION == 1 )\r
189         {\r
190                 extern void vFullDemoIdleHook( void );\r
191 \r
192                 /* When the full demo is build the idle hook is used to create some\r
193                 timers to flash LEDs. */\r
194                 vFullDemoIdleHook();\r
195         }\r
196         #endif\r
197 }\r
198 /*-----------------------------------------------------------*/\r
199 \r
200 void vAssertCalled( const char * pcFile, unsigned long ulLine )\r
201 {\r
202 volatile unsigned long ul = 0;\r
203 \r
204         ( void ) pcFile;\r
205         ( void ) ulLine;\r
206 \r
207         taskENTER_CRITICAL();\r
208         {\r
209                 /* Set ul to a non-zero value using the debugger to step out of this\r
210                 function. */\r
211                 while( ul == 0 )\r
212                 {\r
213                         portNOP();\r
214                 }\r
215         }\r
216         taskEXIT_CRITICAL();\r
217 }\r
218 /*-----------------------------------------------------------*/\r
219 \r
220 void vApplicationTickHook( void )\r
221 {\r
222         #if( mainSELECTED_APPLICATION == 1 )\r
223         {\r
224                 extern void vFullDemoTickHook( void );\r
225 \r
226                 /* When the full demo is build the tick hook is used to demonstrate\r
227                 functions being called from an interrupt and perform some tests. */\r
228                 vFullDemoTickHook();\r
229         }\r
230         #endif\r
231 }\r
232 /*-----------------------------------------------------------*/\r
233 \r
234 /* This is an application defined callback function used to install the tick\r
235 interrupt handler.  It is provided as an application callback because the kernel\r
236 will run on lots of different MicroBlaze and FPGA configurations - not all of\r
237 which will have the same timer peripherals defined or available.  This example\r
238 uses the Dual Timer 0.  If that is available on your hardware platform then this\r
239 example callback implementation may not require modification.   The name of the\r
240 interrupt handler that must be installed is vPortTickISR(), which the function\r
241 below declares as an extern. */\r
242 void vApplicationSetupTimerInterrupt( void )\r
243 {\r
244 portBASE_TYPE xStatus;\r
245 const unsigned char ucTickTimerCounterNumber = ( unsigned char ) 0U;\r
246 const unsigned char ucRunTimeStatsCounterNumber = ( unsigned char ) 1U;\r
247 const unsigned long ulCounterValue = ( ( XPAR_TMRCTR_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL );\r
248 extern void vPortTickISR( void *pvUnused );\r
249 \r
250         /* Initialise the timer/counter. */\r
251         xStatus = XTmrCtr_Initialize( &xTickTimerInstance, XPAR_TMRCTR_0_DEVICE_ID );\r
252 \r
253         if( xStatus == XST_SUCCESS )\r
254         {\r
255                 /* Install the tick interrupt handler as the timer ISR.\r
256                 *NOTE* The xPortInstallInterruptHandler() API function must be used for\r
257                 this purpose. */\r
258                 xStatus = xPortInstallInterruptHandler( XPAR_INTC_0_TMRCTR_0_VEC_ID, vPortTickISR, NULL );\r
259         }\r
260 \r
261         if( xStatus == pdPASS )\r
262         {\r
263                 /* Enable the timer interrupt in the interrupt controller.\r
264                 *NOTE* The vPortEnableInterrupt() API function must be used for this\r
265                 purpose. */\r
266                 vPortEnableInterrupt( XPAR_INTC_0_TMRCTR_0_VEC_ID );\r
267 \r
268                 /* Configure the timer interrupt handler.  This installs the handler\r
269                 directly, rather than through the Xilinx driver.  This is done for\r
270                 efficiency. */\r
271                 XTmrCtr_SetHandler( &xTickTimerInstance, ( void * ) vPortTickISR, NULL );\r
272 \r
273                 /* Set the correct period for the timer. */\r
274                 XTmrCtr_SetResetValue( &xTickTimerInstance, ucTickTimerCounterNumber, ulCounterValue );\r
275 \r
276                 /* Enable the interrupts.  Auto-reload mode is used to generate a\r
277                 periodic tick.  Note that interrupts are disabled when this function is\r
278                 called, so interrupts will not start to be processed until the first\r
279                 task has started to run. */\r
280                 XTmrCtr_SetOptions( &xTickTimerInstance, ucTickTimerCounterNumber, ( XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_DOWN_COUNT_OPTION ) );\r
281 \r
282                 /* Start the timer. */\r
283                 XTmrCtr_Start( &xTickTimerInstance, ucTickTimerCounterNumber );\r
284 \r
285 \r
286 \r
287 \r
288                 /* The second timer is used as the time base for the run time stats.\r
289                 Auto-reload mode is used to ensure the timer does not stop. */\r
290                 XTmrCtr_SetOptions( &xTickTimerInstance, ucRunTimeStatsCounterNumber, XTC_AUTO_RELOAD_OPTION );\r
291 \r
292                 /* Start the timer. */\r
293                 XTmrCtr_Start( &xTickTimerInstance, ucRunTimeStatsCounterNumber );\r
294         }\r
295 \r
296         /* Sanity check that the function executed as expected. */\r
297         configASSERT( ( xStatus == pdPASS ) );\r
298 }\r
299 /*-----------------------------------------------------------*/\r
300 \r
301 /* This is an application defined callback function used to clear whichever\r
302 interrupt was installed by the the vApplicationSetupTimerInterrupt() callback\r
303 function.  It is provided as an application callback because the kernel will run\r
304 on lots of different MicroBlaze and FPGA configurations - not all of which will\r
305 have the same timer peripherals defined or available.  This example uses the\r
306 dual timer 0.  If that is available on your hardware platform then this example\r
307 callback implementation will not require modification provided the example\r
308 definition of vApplicationSetupTimerInterrupt() is also not modified. */\r
309 void vApplicationClearTimerInterrupt( void )\r
310 {\r
311 unsigned long ulCSR;\r
312 \r
313         /* Clear the timer interrupt */\r
314         ulCSR = XTmrCtr_GetControlStatusReg( XPAR_TMRCTR_0_BASEADDR, 0 );\r
315         XTmrCtr_SetControlStatusReg( XPAR_TMRCTR_0_BASEADDR, 0, ulCSR );\r
316 }\r
317 /*-----------------------------------------------------------*/\r
318 \r
319 void *malloc( size_t x )\r
320 {\r
321         /* Just to check it never gets called as there is no heap defined (other\r
322         than the FreeRTOS heap). */\r
323         for( ;; );\r
324 }\r
325 /*-----------------------------------------------------------*/\r
326 \r
327 uint32_t ulMainGetRunTimeCounterValue( void )\r
328 {\r
329 static uint32_t ulOverflows = 0, ulLastTime = 0;\r
330 uint32_t ulTimeNow, ulReturn;\r
331 const uint32_t ulPrescale = 10, ulTCR2Offset = 24UL;\r
332 \r
333         ulTimeNow = * ( ( uint32_t * ) ( XPAR_TMRCTR_0_BASEADDR + ulTCR2Offset ) );\r
334 \r
335         if( ulTimeNow < ulLastTime )\r
336         {\r
337                 /* 32 as its a 32-bit number. */\r
338                 ulOverflows += ( 1UL << ( 32 - ulPrescale ) );\r
339         }\r
340         ulLastTime = ulTimeNow;\r
341 \r
342         ulReturn = ( ulTimeNow >> ulPrescale ) + ulOverflows;\r
343 \r
344         return ulReturn;\r
345 }\r
346 /*-----------------------------------------------------------*/\r
347 \r
348 \r