2 FreeRTOS V7.4.1 - Copyright (C) 2013 Real Time Engineers Ltd.
\r
4 FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT
\r
5 http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
10 * Complete, revised, and edited pdf reference manuals are also *
\r
13 * Purchasing FreeRTOS documentation will not only help you, by *
\r
14 * ensuring you get running as quickly as possible and with an *
\r
15 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
16 * the FreeRTOS project to continue with its mission of providing *
\r
17 * professional grade, cross platform, de facto standard solutions *
\r
18 * for microcontrollers - completely free of charge! *
\r
20 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
22 * Thank you for using FreeRTOS, and thank you for your support! *
\r
24 ***************************************************************************
\r
27 This file is part of the FreeRTOS distribution.
\r
29 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
30 the terms of the GNU General Public License (version 2) as published by the
\r
31 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
33 >>>>>>NOTE<<<<<< The modification to the GPL is included to allow you to
\r
34 distribute a combined work that includes FreeRTOS without being obliged to
\r
35 provide the source code for proprietary components outside of the FreeRTOS
\r
38 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
39 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
40 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
\r
41 details. You should have received a copy of the GNU General Public License
\r
42 and the FreeRTOS license exception along with FreeRTOS; if not it can be
\r
43 viewed here: http://www.freertos.org/a00114.html and also obtained by
\r
44 writing to Real Time Engineers Ltd., contact details for whom are available
\r
45 on the FreeRTOS WEB site.
\r
49 ***************************************************************************
\r
51 * Having a problem? Start by reading the FAQ "My application does *
\r
52 * not run, what could be wrong?" *
\r
54 * http://www.FreeRTOS.org/FAQHelp.html *
\r
56 ***************************************************************************
\r
59 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
60 license and Real Time Engineers Ltd. contact details.
\r
62 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
63 including FreeRTOS+Trace - an indispensable productivity tool, and our new
\r
64 fully thread aware and reentrant UDP/IP stack.
\r
66 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
67 Integrity Systems, who sell the code with commercial support,
\r
68 indemnification and middleware, under the OpenRTOS brand.
\r
70 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
71 engineered and independently SIL3 certified version for use in safety and
\r
72 mission critical applications that require provable dependability.
\r
75 /* ****************************************************************************
\r
76 * main-blinky.c is included when the "Blinky" build configuration is used.
\r
77 * main-full.c is included when the "Full" build configuration is used.
\r
79 * main-full.c creates a lot of demo and test tasks and timers, and is
\r
80 * therefore very comprehensive but also complex. If you would prefer a much
\r
81 * simpler project to get started with, then select the 'Blinky' build
\r
82 * configuration within the SDK Eclipse IDE. See the documentation page for
\r
83 * this demo on the http://www.FreeRTOS.org web site for more information.
\r
84 * ****************************************************************************
\r
86 * main() creates all the demo application tasks and timers, then starts the
\r
87 * scheduler. The web documentation provides more details of the standard demo
\r
88 * application tasks, which provide no particular functionality, but do provide
\r
89 * a good example of how to use the FreeRTOS API.
\r
91 * In addition to the standard demo tasks, the following tasks and tests are
\r
92 * defined and/or created within this file:
\r
94 * TCP/IP ("lwIP") task - lwIP is used to create a basic web server. The web
\r
95 * server uses server side includes (SSI) to generate tables of task statistics,
\r
96 * and run time statistics (run time statistics show how much processing time
\r
97 * each task has consumed). See
\r
98 * http://www.FreeRTOS.org/Free-RTOS-for-Xilinx-MicroBlaze-on-Spartan-6-FPGA.html
\r
99 * for details on setting up and using the embedded web server.
\r
101 * "Reg test" tasks - These test the task context switch mechanism by first
\r
102 * filling the MicroBlaze registers with known values, before checking that each
\r
103 * register maintains the value that was written to it as the tasks are switched
\r
104 * in and out. The two register test tasks do not use the same values, and
\r
105 * execute at a very low priority, to ensure they are pre-empted regularly.
\r
107 * "Check" timer - The check timer period is initially set to five seconds.
\r
108 * The check timer callback function checks that all the standard demo tasks,
\r
109 * and the register check tasks, are not only still executing, but are executing
\r
110 * without reporting any errors. If the check timer discovers that a task has
\r
111 * either stalled, or reported an error, then it changes its own period from
\r
112 * the initial five seconds, to just 200ms. The check timer callback function
\r
113 * also toggles an LED each time it is called. This provides a visual
\r
114 * indication of the system status: If the LED toggles every five seconds then
\r
115 * no issues have been discovered. If the LED toggles every 200ms then an issue
\r
116 * has been discovered with at least one task. The last reported issue is
\r
117 * latched into the pcStatusMessage variable, and can also be viewed at the
\r
118 * bottom of the pages served by the embedded web server.
\r
120 * ***NOTE*** This demo uses the standard comtest tasks, which has special
\r
121 * hardware requirements. See
\r
122 * http://www.FreeRTOS.org/Free-RTOS-for-Xilinx-MicroBlaze-on-Spartan-6-FPGA.html
\r
123 * for more information.
\r
125 * This file also includes example implementations of the
\r
126 * vApplicationIdleHook(), vApplicationStackOverflowHook(),
\r
127 * vApplicationMallocFailedHook(), vApplicationClearTimerInterrupt(), and
\r
128 * vApplicationSetupTimerInterrupt() callback (hook) functions.
\r
131 /* Standard includes. */
\r
132 #include <string.h>
\r
135 /* BSP includes. */
\r
136 #include "xtmrctr.h"
\r
137 #include "microblaze_exceptions_g.h"
\r
139 /* Kernel includes. */
\r
140 #include "FreeRTOS.h"
\r
142 #include "timers.h"
\r
144 /* Standard demo includes. */
\r
145 #include "partest.h"
\r
147 #include "BlockQ.h"
\r
149 #include "blocktim.h"
\r
150 #include "semtest.h"
\r
152 #include "GenQTest.h"
\r
154 #include "recmutex.h"
\r
156 #include "dynamic.h"
\r
157 #include "comtest_strings.h"
\r
158 #include "TimerDemo.h"
\r
160 /* lwIP includes. */
\r
161 #include "lwip/tcpip.h"
\r
164 /* Priorities at which the various tasks are created. */
\r
165 #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
166 #define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
\r
167 #define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
168 #define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
\r
169 #define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
\r
170 #define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
\r
171 #define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
\r
172 #define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
\r
173 #define mainFLOP_TASK_PRIORITY ( tskIDLE_PRIORITY )
\r
175 /* The LED toggled by the check task. */
\r
176 #define mainCHECK_LED ( 3 )
\r
178 /* The rate at which mainCHECK_LED will toggle when all the tasks are running
\r
179 without error. See the description of the check timer in the comments at the
\r
180 top of this file. */
\r
181 #define mainNO_ERROR_CHECK_TIMER_PERIOD ( 5000 / portTICK_RATE_MS )
\r
183 /* The rate at which mainCHECK_LED will toggle when an error has been reported
\r
184 by at least one task. See the description of the check timer in the comments at
\r
185 the top of this file. */
\r
186 #define mainERROR_CHECK_TIMER_PERIOD ( 200 / portTICK_RATE_MS )
\r
188 /* A block time of zero simply means "don't block". */
\r
189 #define mainDONT_BLOCK ( ( portTickType ) 0 )
\r
191 /* The LED used by the comtest tasks. See the comtest_strings.c file for more
\r
192 information. In this case an invalid LED number is provided as all four
\r
193 available LEDs (LEDs 0 to 3) are already in use. */
\r
194 #define mainCOM_TEST_LED ( 4 )
\r
196 /* Baud rate used by the comtest tasks. The baud rate used is actually fixed in
\r
197 UARTLite IP when the hardware was built, but the standard serial init function
\r
198 required a baud rate parameter to be provided - in this case it is just
\r
200 #define mainCOM_TEST_BAUD_RATE ( XPAR_RS232_UART_1_BAUDRATE )
\r
202 /* The timer test task generates a lot of timers that all use a different
\r
203 period that is a multiple of the mainTIMER_TEST_PERIOD definition. */
\r
204 #define mainTIMER_TEST_PERIOD ( 20 )
\r
206 /*-----------------------------------------------------------*/
\r
209 * The register test tasks as described in the comments at the top of this file.
\r
210 * The nature of the register test tasks means they have to be implemented in
\r
213 extern void vRegisterTest1( void *pvParameters );
\r
214 extern void vRegisterTest2( void *pvParameters );
\r
217 * Defines the 'check' timer functionality as described at the top of this file.
\r
218 * This function is the callback function associated with the 'check' timer.
\r
220 static void vCheckTimerCallback( xTimerHandle xTimer );
\r
223 * Configure the interrupt controller, LED outputs and button inputs.
\r
225 static void prvSetupHardware( void );
\r
227 /* Defined in lwIPApps.c. */
\r
228 extern void lwIPAppsInit( void *pvArguments );
\r
230 /*-----------------------------------------------------------*/
\r
232 /* The check timer callback function sets pcStatusMessage to a string that
\r
233 indicates the last reported error that it discovered. */
\r
234 static const char *pcStatusMessage = NULL;
\r
236 /* Structures that hold the state of the various peripherals used by this demo.
\r
237 These are used by the Xilinx peripheral driver API functions. In this case,
\r
238 only the timer/counter is used directly within this file. */
\r
239 static XTmrCtr xTimer0Instance;
\r
241 /* The 'check' timer, as described at the top of this file. */
\r
242 static xTimerHandle xCheckTimer = NULL;
\r
244 /* Used in the run time stats calculations. */
\r
245 static unsigned long ulClocksPer10thOfAMilliSecond = 0UL;
\r
247 /* Constants used to set up the AXI timer to generate ticks. */
\r
248 static const unsigned char ucTimerCounterNumber = ( unsigned char ) 0U;
\r
249 static const unsigned long ulCounterReloadValue = ( ( XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL );
\r
251 /*-----------------------------------------------------------*/
\r
255 /***************************************************************************
\r
256 This project includes a lot of demo and test tasks and timers, and is
\r
257 therefore comprehensive, but complex. If you would prefer a much simpler
\r
258 project to get started with, then select the 'Blinky' build configuration
\r
259 within the SDK Eclipse IDE.
\r
260 ***************************************************************************/
\r
262 /* Configure the interrupt controller, LED outputs and button inputs. */
\r
263 prvSetupHardware();
\r
265 /* This call creates the TCP/IP thread. */
\r
266 tcpip_init( lwIPAppsInit, NULL );
\r
268 /* Start the reg test tasks, as described in the comments at the top of this
\r
270 xTaskCreate( vRegisterTest1, ( const signed char * const ) "RegTst1", configMINIMAL_STACK_SIZE, ( void * ) 0, tskIDLE_PRIORITY, NULL );
\r
271 xTaskCreate( vRegisterTest2, ( const signed char * const ) "RegTst2", configMINIMAL_STACK_SIZE, ( void * ) 0, tskIDLE_PRIORITY, NULL );
\r
273 /* Create the standard demo tasks. */
\r
274 vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
\r
275 vCreateBlockTimeTasks();
\r
276 vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
\r
277 vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
\r
278 vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );
\r
279 vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );
\r
280 vStartQueuePeekTasks();
\r
281 vStartRecursiveMutexTasks();
\r
282 vStartComTestStringsTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );
\r
283 vStartDynamicPriorityTasks();
\r
284 vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
\r
286 /* Note - the set of standard demo tasks contains two versions of
\r
287 vStartMathTasks.c. One is defined in flop.c, and uses double precision
\r
288 floating point numbers and variables. The other is defined in sp_flop.c,
\r
289 and uses single precision floating point numbers and variables. The
\r
290 MicroBlaze floating point unit only handles single precision floating.
\r
291 Therefore, to test the floating point hardware, sp_flop.c should be included
\r
292 in this project. */
\r
293 vStartMathTasks( mainFLOP_TASK_PRIORITY );
\r
295 /* The suicide tasks must be created last as they need to know how many
\r
296 tasks were running prior to their creation. This then allows them to
\r
297 ascertain whether or not the correct/expected number of tasks are running at
\r
299 vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
\r
301 /* Create the 'check' timer - the timer that periodically calls the
\r
302 check function as described in the comments at the top of this file. Note
\r
303 that, for reasons stated in the comments within vApplicationIdleHook()
\r
304 (defined in this file), the check timer is not actually started until after
\r
305 the scheduler has been started. */
\r
306 xCheckTimer = xTimerCreate( ( const signed char * ) "Check timer", mainNO_ERROR_CHECK_TIMER_PERIOD, pdTRUE, ( void * ) 0, vCheckTimerCallback );
\r
308 /* Start the scheduler running. From this point on, only tasks and
\r
309 interrupts will be executing. */
\r
310 vTaskStartScheduler();
\r
312 /* If all is well then the following line will never be reached. If
\r
313 execution does reach here, then it is highly probably that the heap size
\r
314 is too small for the idle and/or timer tasks to be created within
\r
315 vTaskStartScheduler(). */
\r
316 taskDISABLE_INTERRUPTS();
\r
319 /*-----------------------------------------------------------*/
\r
321 static void vCheckTimerCallback( xTimerHandle xTimer )
\r
323 extern unsigned long ulRegTest1CycleCount, ulRegTest2CycleCount;
\r
324 static volatile unsigned long ulLastRegTest1CycleCount = 0UL, ulLastRegTest2CycleCount = 0UL;
\r
325 static long lErrorAlreadyLatched = pdFALSE;
\r
326 portTickType xExecutionRate = mainNO_ERROR_CHECK_TIMER_PERIOD;
\r
328 /* This is the callback function used by the 'check' timer, as described
\r
329 in the comments at the top of this file. */
\r
331 /* Don't overwrite any errors that have already been latched. */
\r
332 if( pcStatusMessage == NULL )
\r
334 /* Check the standard demo tasks are running without error. */
\r
335 if( xAreGenericQueueTasksStillRunning() != pdTRUE )
\r
337 pcStatusMessage = "Error: GenQueue";
\r
339 else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
\r
341 pcStatusMessage = "Error: QueuePeek\r\n";
\r
343 else if( xAreBlockingQueuesStillRunning() != pdTRUE )
\r
345 pcStatusMessage = "Error: BlockQueue\r\n";
\r
347 else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
\r
349 pcStatusMessage = "Error: BlockTime\r\n";
\r
351 else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
\r
353 pcStatusMessage = "Error: SemTest\r\n";
\r
355 else if( xArePollingQueuesStillRunning() != pdTRUE )
\r
357 pcStatusMessage = "Error: PollQueue\r\n";
\r
359 else if( xIsCreateTaskStillRunning() != pdTRUE )
\r
361 pcStatusMessage = "Error: Death\r\n";
\r
363 else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
\r
365 pcStatusMessage = "Error: RecMutex\r\n";
\r
367 else if( xAreMathsTaskStillRunning() != pdPASS )
\r
369 pcStatusMessage = "Error: Flop\r\n";
\r
371 else if( xAreComTestTasksStillRunning() != pdPASS )
\r
373 pcStatusMessage = "Error: Comtest\r\n";
\r
375 else if( xAreDynamicPriorityTasksStillRunning() != pdPASS )
\r
377 pcStatusMessage = "Error: Dynamic\r\n";
\r
379 else if( xAreTimerDemoTasksStillRunning( xExecutionRate ) != pdTRUE )
\r
381 pcStatusMessage = "Error: TimerDemo";
\r
383 else if( ulRegTest1CycleCount == ulLastRegTest1CycleCount )
\r
385 /* Check the reg test tasks are still cycling. They will stop
\r
386 incrementing their loop counters if they encounter an error. */
\r
387 pcStatusMessage = "Error: RegTest1\r\n";
\r
389 else if( ulRegTest2CycleCount == ulLastRegTest2CycleCount )
\r
391 pcStatusMessage = "Error: RegTest2\r\n";
\r
395 /* Store a local copy of the current reg test loop counters. If these have
\r
396 not incremented the next time this callback function is executed then the
\r
397 reg test tasks have either stalled or discovered an error. */
\r
398 ulLastRegTest1CycleCount = ulRegTest1CycleCount;
\r
399 ulLastRegTest2CycleCount = ulRegTest2CycleCount;
\r
401 /* Toggle the check LED to give an indication of the system status. If
\r
402 the LED toggles every 5 seconds then everything is ok. A faster toggle
\r
403 indicates an error. */
\r
404 vParTestToggleLED( mainCHECK_LED );
\r
406 if( pcStatusMessage != NULL )
\r
408 if( lErrorAlreadyLatched == pdFALSE )
\r
410 /* An error has occurred, so change the period of the timer that
\r
411 calls this callback function. This results in the LED toggling at
\r
412 a faster rate - giving the user visual feedback that something is not
\r
413 as it should be. This function is called from the context of the
\r
414 timer service task so must ***not*** attempt to block while calling
\r
416 if( xTimerChangePeriod( xTimer, mainERROR_CHECK_TIMER_PERIOD, mainDONT_BLOCK ) == pdPASS )
\r
418 /* If the command to change the timer period was sent to the
\r
419 timer command queue successfully, then latch the fact that the
\r
420 timer period has already been changed. This is just done to
\r
421 prevent xTimerChangePeriod() being called on every execution of
\r
422 this function once an error has been discovered. */
\r
423 lErrorAlreadyLatched = pdTRUE;
\r
426 /* Update the xExecutionRate variable too as the rate at which this
\r
427 callback is executed has to be passed into the
\r
428 xAreTimerDemoTasksStillRunning() function. */
\r
429 xExecutionRate = mainERROR_CHECK_TIMER_PERIOD;
\r
433 /*-----------------------------------------------------------*/
\r
435 /* This is an application defined callback function used to install the tick
\r
436 interrupt handler. It is provided as an application callback because the kernel
\r
437 will run on lots of different MicroBlaze and FPGA configurations - not all of
\r
438 which will have the same timer peripherals defined or available. This example
\r
439 uses the AXI Timer 0. If that is available on your hardware platform then this
\r
440 example callback implementation should not require modification. The name of
\r
441 the interrupt handler that should be installed is vPortTickISR(), which the
\r
442 function below declares as an extern. */
\r
443 void vApplicationSetupTimerInterrupt( void )
\r
445 portBASE_TYPE xStatus;
\r
446 extern void vPortTickISR( void *pvUnused );
\r
448 /* Initialise the timer/counter. */
\r
449 xStatus = XTmrCtr_Initialize( &xTimer0Instance, XPAR_AXI_TIMER_0_DEVICE_ID );
\r
451 if( xStatus == XST_SUCCESS )
\r
453 /* Install the tick interrupt handler as the timer ISR.
\r
454 *NOTE* The xPortInstallInterruptHandler() API function must be used for
\r
456 xStatus = xPortInstallInterruptHandler( XPAR_INTC_0_TMRCTR_0_VEC_ID, vPortTickISR, NULL );
\r
459 if( xStatus == pdPASS )
\r
461 /* Enable the timer interrupt in the interrupt controller.
\r
462 *NOTE* The vPortEnableInterrupt() API function must be used for this
\r
464 vPortEnableInterrupt( XPAR_INTC_0_TMRCTR_0_VEC_ID );
\r
466 /* Configure the timer interrupt handler. */
\r
467 XTmrCtr_SetHandler( &xTimer0Instance, ( void * ) vPortTickISR, NULL );
\r
469 /* Set the correct period for the timer. */
\r
470 XTmrCtr_SetResetValue( &xTimer0Instance, ucTimerCounterNumber, ulCounterReloadValue );
\r
472 /* Enable the interrupts. Auto-reload mode is used to generate a
\r
473 periodic tick. Note that interrupts are disabled when this function is
\r
474 called, so interrupts will not start to be processed until the first
\r
475 task has started to run. */
\r
476 XTmrCtr_SetOptions( &xTimer0Instance, ucTimerCounterNumber, ( XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_DOWN_COUNT_OPTION ) );
\r
478 /* Start the timer. */
\r
479 XTmrCtr_Start( &xTimer0Instance, ucTimerCounterNumber );
\r
482 /* Sanity check that the function executed as expected. */
\r
483 configASSERT( ( xStatus == pdPASS ) );
\r
485 /*-----------------------------------------------------------*/
\r
487 /* This is an application defined callback function used to clear whichever
\r
488 interrupt was installed by the the vApplicationSetupTimerInterrupt() callback
\r
489 function - in this case the interrupt generated by the AXI timer. It is
\r
490 provided as an application callback because the kernel will run on lots of
\r
491 different MicroBlaze and FPGA configurations - not all of which will have the
\r
492 same timer peripherals defined or available. This example uses the AXI Timer 0.
\r
493 If that is available on your hardware platform then this example callback
\r
494 implementation should not require modification provided the example definition
\r
495 of vApplicationSetupTimerInterrupt() is also not modified. */
\r
496 void vApplicationClearTimerInterrupt( void )
\r
498 unsigned long ulCSR;
\r
500 /* Clear the timer interrupt */
\r
501 ulCSR = XTmrCtr_GetControlStatusReg( XPAR_AXI_TIMER_0_BASEADDR, 0 );
\r
502 XTmrCtr_SetControlStatusReg( XPAR_AXI_TIMER_0_BASEADDR, 0, ulCSR );
\r
504 /*-----------------------------------------------------------*/
\r
506 void vApplicationMallocFailedHook( void )
\r
508 /* vApplicationMallocFailedHook() will only be called if
\r
509 configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
\r
510 function that will get called if a call to pvPortMalloc() fails.
\r
511 pvPortMalloc() is called internally by the kernel whenever a task, queue or
\r
512 semaphore is created. It is also called by various parts of the demo
\r
513 application. If heap_1.c or heap_2.c are used, then the size of the heap
\r
514 available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
\r
515 FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
\r
516 to query the size of free heap space that remains (although it does not
\r
517 provide information on how the remaining heap might be fragmented). */
\r
518 taskDISABLE_INTERRUPTS();
\r
521 /*-----------------------------------------------------------*/
\r
523 void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )
\r
525 ( void ) pcTaskName;
\r
528 /* vApplicationStackOverflowHook() will only be called if
\r
529 configCHECK_FOR_STACK_OVERFLOW is set to either 1 or 2. The handle and name
\r
530 of the offending task will be passed into the hook function via its
\r
531 parameters. However, when a stack has overflowed, it is possible that the
\r
532 parameters will have been corrupted, in which case the pxCurrentTCB variable
\r
533 can be inspected directly. */
\r
534 taskDISABLE_INTERRUPTS();
\r
537 /*-----------------------------------------------------------*/
\r
539 void vApplicationIdleHook( void )
\r
541 static long lCheckTimerStarted = pdFALSE;
\r
543 /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
\r
544 to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
\r
545 task. It is essential that code added to this hook function never attempts
\r
546 to block in any way (for example, call xQueueReceive() with a block time
\r
547 specified, or call vTaskDelay()). If the application makes use of the
\r
548 vTaskDelete() API function (as this demo application does) then it is also
\r
549 important that vApplicationIdleHook() is permitted to return to its calling
\r
550 function, because it is the responsibility of the idle task to clean up
\r
551 memory allocated by the kernel to any task that has since been deleted. */
\r
553 /* If the check timer has not already been started, then start it now.
\r
554 Normally, the xTimerStart() API function can be called immediately after the
\r
555 timer is created - how this demo application includes the timer demo tasks.
\r
556 The timer demo tasks, as part of their test function, deliberately fill up
\r
557 the timer command queue - meaning the check timer cannot be started until
\r
558 after the scheduler has been started - at which point the timer command
\r
559 queue will have been drained. */
\r
560 if( lCheckTimerStarted == pdFALSE )
\r
562 xTimerStart( xCheckTimer, mainDONT_BLOCK );
\r
563 lCheckTimerStarted = pdTRUE;
\r
566 /*-----------------------------------------------------------*/
\r
568 void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump )
\r
570 ( void ) xRegisterDump;
\r
572 /* If configINSTALL_EXCEPTION_HANDLERS is set to 1 in FreeRTOSConfig.h, then
\r
573 the kernel will automatically install its own exception handlers before the
\r
574 kernel is started, if the application writer has not already caused them to
\r
575 be installed by calling either of the vPortExceptionsInstallHandlers()
\r
576 or xPortInstallInterruptHandler() API functions before that time. The
\r
577 kernels exception handler populates an xPortRegisterDump structure with
\r
578 the processor state at the point that the exception was triggered - and also
\r
579 includes a strings that say what the exception cause was and which task was
\r
580 running at the time. The exception handler then passes the populated
\r
581 xPortRegisterDump structure into vApplicationExceptionRegisterDump() to
\r
582 allow the application writer to perform any debugging that may be necessary.
\r
583 However, defining vApplicationExceptionRegisterDump() within the application
\r
584 itself is optional. The kernel will use a default implementation if the
\r
585 application writer chooses not to provide their own. */
\r
591 /*-----------------------------------------------------------*/
\r
593 static void prvSetupHardware( void )
\r
595 taskDISABLE_INTERRUPTS();
\r
597 /* Configure the LED outputs. */
\r
598 vParTestInitialise();
\r
600 /* Tasks inherit the exception and cache configuration of the MicroBlaze
\r
601 at the point that they are created. */
\r
602 #if MICROBLAZE_EXCEPTIONS_ENABLED == 1
\r
603 microblaze_enable_exceptions();
\r
606 #if XPAR_MICROBLAZE_USE_ICACHE == 1
\r
607 microblaze_invalidate_icache();
\r
608 microblaze_enable_icache();
\r
611 #if XPAR_MICROBLAZE_USE_DCACHE == 1
\r
612 microblaze_invalidate_dcache();
\r
613 microblaze_enable_dcache();
\r
617 /*-----------------------------------------------------------*/
\r
619 void vMainConfigureTimerForRunTimeStats( void )
\r
621 /* How many times does the counter counter increment in 10ms? */
\r
622 ulClocksPer10thOfAMilliSecond = XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / 10000UL;
\r
624 /*-----------------------------------------------------------*/
\r
626 unsigned long ulMainGetRunTimeCounterValue( void )
\r
628 unsigned long ulTimerCounts1, ulTimerCounts2, ulTickCount, ulReturn;
\r
630 /* NOTE: This can get called from a yield, in which case interrupts are
\r
631 disabled, or from a tick ISR, in which case the effect is the same as if
\r
632 interrupts were disabled. In either case, it is going to run atomically. */
\r
634 /* The timer is in down count mode. How many clocks have passed since it
\r
635 was last reloaded? */
\r
636 ulTimerCounts1 = ulCounterReloadValue - XTmrCtr_GetValue( &xTimer0Instance, ucTimerCounterNumber );
\r
638 /* How many times has it overflowed? */
\r
639 ulTickCount = xTaskGetTickCountFromISR();
\r
641 /* If this is being called from a yield, has the counter overflowed since
\r
642 it was read? If that is the case then ulTickCounts will need incrementing
\r
643 again as it will not yet have been incremented from the tick interrupt. */
\r
644 ulTimerCounts2 = ulCounterReloadValue - XTmrCtr_GetValue( &xTimer0Instance, ucTimerCounterNumber );
\r
645 if( ulTimerCounts2 < ulTimerCounts1 )
\r
647 /* There is a tick interrupt pending but the tick count not yet
\r
651 /* Use the second timer reading. */
\r
652 ulTimerCounts1 = ulTimerCounts2;
\r
655 /* Convert the tick count into tenths of a millisecond. THIS ASSUMES
\r
656 configTICK_RATE_HZ is 1000! */
\r
657 ulReturn = ( ulTickCount * 10UL );
\r
659 /* Add on the number of tenths of a millisecond that have passed since the
\r
660 tick count last got updated. */
\r
661 ulReturn += ( ulTimerCounts1 / ulClocksPer10thOfAMilliSecond );
\r
663 /* Some crude rounding. */
\r
664 if( ( ulTimerCounts1 % ulClocksPer10thOfAMilliSecond ) > ( ulClocksPer10thOfAMilliSecond >> 1UL ) )
\r
671 /*-----------------------------------------------------------*/
\r
673 char *pcMainGetTaskStatusMessage( void )
\r
677 if( pcStatusMessage == NULL )
\r
679 pcReturn = ( char * ) "OK";
\r
683 pcReturn = ( char * ) pcStatusMessage;
\r