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