From 7acba9aeae9b6c9fcbd9915f6755863e07c4aa89 Mon Sep 17 00:00:00 2001 From: richardbarry Date: Wed, 29 Jun 2011 19:03:59 +0000 Subject: [PATCH] Continue commenting the new MicroBlaze demo. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1475 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../CreateProjectDirectoryStructure.bat | 2 + .../RTOSDemoSource/FreeRTOSConfig.h | 4 +- .../RTOSDemoSource/FreeRTOS_Source/timers.c | 2 - .../SDKProjects/RTOSDemoSource/main-blinky.c | 24 ++- .../SDKProjects/RTOSDemoSource/main-full.c | 186 ++++++++---------- 5 files changed, 97 insertions(+), 121 deletions(-) diff --git a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/CreateProjectDirectoryStructure.bat b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/CreateProjectDirectoryStructure.bat index c68237c07..bbe76c925 100644 --- a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/CreateProjectDirectoryStructure.bat +++ b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/CreateProjectDirectoryStructure.bat @@ -48,6 +48,7 @@ IF EXIST FreeRTOS_Source Goto END copy ..\..\..\Common\minimal\sp_flop.c Demo_Source copy ..\..\..\Common\minimal\flash.c Demo_Source copy ..\..\..\Common\minimal\comtest_strings.c Demo_Source + copy ..\..\..\Common\minimal\TimerDemo.c Demo_Source REM Copy the common demo file headers. copy ..\..\..\Common\include\dynamic.h Demo_Source\include @@ -65,5 +66,6 @@ IF EXIST FreeRTOS_Source Goto END copy ..\..\..\Common\include\comtest_strings.h Demo_Source\include copy ..\..\..\Common\include\serial.h Demo_Source\include copy ..\..\..\Common\include\comtest.h Demo_Source\include + copy ..\..\..\Common\include\TimerDemo.h Demo_Source\include : END diff --git a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOSConfig.h b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOSConfig.h index 7e0e3803c..7082a7dbc 100644 --- a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOSConfig.h +++ b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOSConfig.h @@ -77,10 +77,10 @@ *----------------------------------------------------------*/ #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 1 -#define configUSE_TICK_HOOK 0 +#define configUSE_TICK_HOOK 1 #define configCPU_CLOCK_HZ ( XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ ) /* Not actually used in this demo as the timer is set up in main() and uses the peripheral clock, not the CPU clock. */ #define configTICK_RATE_HZ ( ( portTickType ) 1000 ) -#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 6 ) +#define configMAX_PRIORITIES ( 6 ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 64 * 1024 ) ) #define configMAX_TASK_NAME_LEN ( 10 ) #define configUSE_TRACE_FACILITY 0 diff --git a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/timers.c b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/timers.c index 5d47efd40..7e5ef22ad 100644 --- a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/timers.c +++ b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/FreeRTOS_Source/timers.c @@ -311,8 +311,6 @@ portBASE_TYPE xListWasEmpty; /* Just to avoid compiler warnings. */ ( void ) pvParameters; - vTaskDelay( 2 ); - for( ;; ) { /* Query the timers list to see if it contains any timers, and if so, diff --git a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/main-blinky.c b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/main-blinky.c index 706992f8f..efc633dfe 100644 --- a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/main-blinky.c +++ b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/main-blinky.c @@ -113,11 +113,8 @@ #include "queue.h" #include "timers.h" -/* BSP includes. *///_RB_ which of these can be removed? -#include "xenv_standalone.h" +/* BSP includes. */ #include "xtmrctr.h" -#include "xil_exception.h" -#include "microblaze_exceptions_g.h" #include "xgpio.h" /* Priorities at which the tasks are created. */ @@ -196,6 +193,13 @@ static const unsigned long ulGPIOOutputChannel = 1UL, ulGPIOInputChannel = 1UL; int main( void ) { + /* ************************************************************************* + This is a very simple project suitable for getting started with FreeRTOS. + If you would prefer a more complex project that demonstrates a lot more + features and tests, then select the 'Full' build configuration within the + SDK Eclipse IDE. + ***************************************************************************/ + /* Configure the interrupt controller, LED outputs and button inputs. */ prvSetupHardware(); @@ -380,10 +384,6 @@ const unsigned char ucSetToOutput = 0U; } configASSERT( ( xStatus == pdPASS ) ); - - #ifdef MICROBLAZE_EXCEPTIONS_ENABLED - microblaze_enable_exceptions(); - #endif } /*-----------------------------------------------------------*/ @@ -430,6 +430,14 @@ volatile size_t xFreeHeapSpace; } /*-----------------------------------------------------------*/ +void vApplicationTickHook( void ) +{ + /* This simple blinky demo does not use the tick hook, but a tick hook is + required to be defined as the blinky and full demos share a + FreeRTOSConfig.h header file. */ +} +/*-----------------------------------------------------------*/ + /* This is an application defined callback function used to install the tick interrupt handler. It is provided as an application callback because the kernel will run on lots of different MicroBlaze and FPGA configurations - not all of diff --git a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/main-full.c b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/main-full.c index ab566c149..39bbd0840 100644 --- a/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/main-full.c +++ b/Demo/MicroBlaze_Spartan-6_EthernetLite/SDKProjects/RTOSDemoSource/main-full.c @@ -52,28 +52,20 @@ */ /* **************************************************************************** - * This project includes a lot of tasks and tests and is therefore complex. - * If you would prefer a much simpler project to get started with then select - * the 'Blinky' build configuration within the Embedded Workbench IDE. + * This project includes a lot of demo and test tasks, and is therefore complex. + * If you would prefer a much simpler project to get started with, then select + * the 'Blinky' build configuration within the SDK Eclipse IDE. * **************************************************************************** * - * Creates all the demo application tasks, then starts the scheduler. The web - * documentation provides more details of the standard demo application tasks, - * which provide no particular functionality but do provide a good example of - * how to use the FreeRTOS API. The tasks defined in flop.c are included in the - * set of standard demo tasks to ensure the floating point unit gets some - * exercise. + * main() creates all the demo application tasks, then starts the scheduler. + * The web documentation provides more details of the standard demo application + * tasks, which provide no particular functionality, but do provide a good + * example of how to use the FreeRTOS API. * * In addition to the standard demo tasks, the following tasks and tests are * defined and/or created within this file: * - * Webserver ("uIP") task - This serves a number of dynamically generated WEB - * pages to a standard WEB browser. The IP and MAC addresses are configured by - * constants defined at the bottom of FreeRTOSConfig.h. Use either a standard - * Ethernet cable to connect through a hug, or a cross over (point to point) - * cable to connect directly. Ensure the IP address used is compatible with the - * IP address of the machine running the browser - the easiest way to achieve - * this is to ensure the first three octets of the IP addresses are the same. + * Webserver ("lwIP") task - TBD _RB_ * * "Reg test" tasks - These fill the registers with known values, then check * that each register still contains its expected value. Each task uses @@ -82,54 +74,32 @@ * test loop. A register containing an unexpected value is indicative of an * error in the context switching mechanism and will result in a branch to a * null loop - which in turn will prevent the check variable from incrementing - * any further and allow the check task (described below) to determine that an + * any further and allow the check timer (described below) to determine that an * error has occurred. The nature of the reg test tasks necessitates that they * are written in assembly code. * - * "Check" task - This only executes every five seconds but has a high priority - * to ensure it gets processor time. Its main function is to check that all the - * standard demo tasks are still operational. While no errors have been - * discovered the check task will toggle LED 5 every 5 seconds - the toggle - * rate increasing to 200ms being a visual indication that at least one task has - * reported unexpected behaviour. + * "Check" timer - The check timer period is initially set to five seconds. + * The check timer callback function checks that all the standard demo tasks are + * functioning as expected, without error. If an error is discovered in any + * standard demo task, then the check timer period is shortened to 200ms. The + * check timer callback function also toggles an LED each time it is called. + * Therefore, if the LED toggles every five seconds, all the tasks are + * functioning as expected, without any error conditions being detected. If the + * LED toggles every 200ms then an error has been discovered in at least one + * task. * - * "High frequency timer test" - A high frequency periodic interrupt is - * generated using a timer - the interrupt is assigned a priority above - * configMAX_SYSCALL_INTERRUPT_PRIORITY so should not be effected by anything - * the kernel is doing. The frequency and priority of the interrupt, in - * combination with other standard tests executed in this demo, should result - * in interrupts nesting at least 3 and probably 4 deep. This test is only - * included in build configurations that have the optimiser switched on. In - * optimised builds the count of high frequency ticks is used as the time base - * for the run time stats. - * - * *NOTE 1* If LED5 is toggling every 5 seconds then all the demo application - * tasks are executing as expected and no errors have been reported in any - * tasks. The toggle rate increasing to 200ms indicates that at least one task - * has reported unexpected behaviour. - * - * *NOTE 2* vApplicationSetupTimerInterrupt() is called by the kernel to let - * the application set up a timer to generate the tick interrupt. In this - * example a compare match timer is used for this purpose. - * - * *NOTE 3* The CPU must be in Supervisor mode when the scheduler is started. - * The PowerON_Reset_PC() supplied in resetprg.c with this demo has - * Change_PSW_PM_to_UserMode() commented out to ensure this is the case. - * - * *NOTE 4* The IntQueue common demo tasks test interrupt nesting and make use - * of all the 8bit timers (as two cascaded 16bit units). -*/ + * This file also includes example implementations of the vApplicationTickHook(), + * vApplicationIdleHook(), vApplicationStackOverflowHook(), + * vApplicationMallocFailedHook(), vApplicationClearTimerInterrupt(), and + * vApplicationSetupTimerInterrupt() callback (hook) functions. + */ /* Standard includes. */ #include #include /* BSP includes. */ -#include "xenv_standalone.h" #include "xtmrctr.h" -#include "xil_exception.h" -#include "microblaze_exceptions_g.h" -#include "xgpio.h" /* Kernel includes. */ #include "FreeRTOS.h" @@ -150,8 +120,7 @@ #include "flop.h" #include "dynamic.h" #include "comtest_strings.h" - -#define xPrintf( x ) +#include "TimerDemo.h" /* Priorities at which the tasks are created. */ #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 ) @@ -195,6 +164,8 @@ when the hardware was built, but the standard serial init function required a baud rate parameter. */ #define mainCOM_TEST_BAUD_RATE ( XPAR_RS232_UART_1_BAUDRATE ) +#define mainTIMER_TEST_PERIOD ( 20 ) + /* * vApplicationMallocFailedHook() will only be called if * configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook @@ -242,10 +213,6 @@ static void vCheckTimerCallback( xTimerHandle xTimer ); static void prvSetupHardware( void ); -/* - * Contains the implementation of the WEB server. - */ -//_RB_extern void vuIP_Task( void *pvParameters ); /*-----------------------------------------------------------*/ @@ -263,6 +230,12 @@ static xTimerHandle xCheckTimer = NULL; int main( void ) { + /* ************************************************************************* + This project includes a lot of demo and test tasks, and is therefore complex. + If you would prefer a much simpler project to get started with, then select + the 'Blinky' build configuration within the SDK Eclipse IDE. + ***************************************************************************/ + /* Configure the interrupt controller, LED outputs and button inputs. */ prvSetupHardware(); @@ -270,9 +243,6 @@ int main( void ) xTaskCreate( vRegisterTest1, ( const signed char * const ) "RegTst1", configMINIMAL_STACK_SIZE, ( void * ) 0, tskIDLE_PRIORITY, NULL ); xTaskCreate( vRegisterTest2, ( const signed char * const ) "RegTst2", configMINIMAL_STACK_SIZE, ( void * ) 0, tskIDLE_PRIORITY, NULL ); - /* The web server task. */ -//_RB_ xTaskCreate( vuIP_Task, "uIP", mainuIP_STACK_SIZE, NULL, mainuIP_TASK_PRIORITY, NULL ); - /* Create the standard demo tasks. */ vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); vCreateBlockTimeTasks(); @@ -283,6 +253,8 @@ int main( void ) vStartQueuePeekTasks(); vStartRecursiveMutexTasks(); vStartComTestStringsTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED ); + vStartDynamicPriorityTasks(); + vStartTimerDemoTask( mainTIMER_TEST_PERIOD ); /* Note - the set of standard demo tasks contains two versions of vStartMathTasks.c. One is defined in flop.c, and uses double precision @@ -305,12 +277,6 @@ int main( void ) until after the scheduler has been started. */ xCheckTimer = xTimerCreate( ( const signed char * ) "Check timer", mainNO_ERROR_CHECK_TIMER_PERIOD, pdTRUE, ( void * ) 0, vCheckTimerCallback ); - /* Ensure the check timer will start running as soon as the scheduler - starts. The block time is set to 0 (mainDONT_BLOCK), but would be - ingnored at this point anyway as block times can only be specified when - the scheduler is running. */ - xTimerStart( xCheckTimer, mainDONT_BLOCK ); - /* Start the tasks running. */ vTaskStartScheduler(); @@ -327,6 +293,7 @@ static void vCheckTimerCallback( xTimerHandle xTimer ) extern unsigned long ulRegTest1CycleCount, ulRegTest2CycleCount; static volatile unsigned long ulLastRegTest1CycleCount = 0UL, ulLastRegTest2CycleCount = 0UL; static long lErrorAlreadyLatched = pdFALSE; +portTickType xExecutionRate = mainNO_ERROR_CHECK_TIMER_PERIOD; /* This is the callback function used by the 'check' timer, as described at the top of this file. */ @@ -338,75 +305,60 @@ static long lErrorAlreadyLatched = pdFALSE; rate at which mainCHECK_LED flashes to give visual feedback that an error has occurred. */ pcStatusMessage = "Error: GenQueue"; - xPrintf( pcStatusMessage ); } - - if( xAreQueuePeekTasksStillRunning() != pdTRUE ) + else if( xAreQueuePeekTasksStillRunning() != pdTRUE ) { pcStatusMessage = "Error: QueuePeek\r\n"; - xPrintf( pcStatusMessage ); } - - if( xAreBlockingQueuesStillRunning() != pdTRUE ) + else if( xAreBlockingQueuesStillRunning() != pdTRUE ) { pcStatusMessage = "Error: BlockQueue\r\n"; - xPrintf( pcStatusMessage ); } - - if( xAreBlockTimeTestTasksStillRunning() != pdTRUE ) + else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE ) { pcStatusMessage = "Error: BlockTime\r\n"; - xPrintf( pcStatusMessage ); } - - if( xAreSemaphoreTasksStillRunning() != pdTRUE ) + else if( xAreSemaphoreTasksStillRunning() != pdTRUE ) { pcStatusMessage = "Error: SemTest\r\n"; - xPrintf( pcStatusMessage ); } - - if( xArePollingQueuesStillRunning() != pdTRUE ) + else if( xArePollingQueuesStillRunning() != pdTRUE ) { pcStatusMessage = "Error: PollQueue\r\n"; - xPrintf( pcStatusMessage ); } - - if( xIsCreateTaskStillRunning() != pdTRUE ) + else if( xIsCreateTaskStillRunning() != pdTRUE ) { pcStatusMessage = "Error: Death\r\n"; - xPrintf( pcStatusMessage ); } - - if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) + else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) { pcStatusMessage = "Error: RecMutex\r\n"; - xPrintf( pcStatusMessage ); } - - if( xAreMathsTaskStillRunning() != pdPASS ) + else if( xAreMathsTaskStillRunning() != pdPASS ) { pcStatusMessage = "Error: Flop\r\n"; - xPrintf( pcStatusMessage ); } - - if( xAreComTestTasksStillRunning() != pdPASS ) + else if( xAreComTestTasksStillRunning() != pdPASS ) { pcStatusMessage = "Error: Comtest\r\n"; - xPrintf( pcStatusMessage ); } - - /* Check the reg test tasks are still cycling. They will stop incrementing - their loop counters if they encounter an error. */ - if( ulRegTest1CycleCount == ulLastRegTest1CycleCount ) + else if( xAreDynamicPriorityTasksStillRunning() != pdPASS ) { + pcStatusMessage = "Error: Dynamic\r\n"; + } + else if( xAreTimerDemoTasksStillRunning( xExecutionRate ) != pdTRUE ) + { + pcStatusMessage = "Error: TimerDemo"; + } + else if( ulRegTest1CycleCount == ulLastRegTest1CycleCount ) + { + /* Check the reg test tasks are still cycling. They will stop + incrementing their loop counters if they encounter an error. */ pcStatusMessage = "Error: RegTest1\r\n"; - xPrintf( pcStatusMessage ); } - - if( ulRegTest2CycleCount == ulLastRegTest2CycleCount ) + else if( ulRegTest2CycleCount == ulLastRegTest2CycleCount ) { pcStatusMessage = "Error: RegTest2\r\n"; - xPrintf( pcStatusMessage ); } ulLastRegTest1CycleCount = ulRegTest1CycleCount; @@ -425,6 +377,11 @@ static long lErrorAlreadyLatched = pdFALSE; This is called from a timer callback so must not attempt to block. */ xTimerChangePeriod( xTimer, mainERROR_CHECK_TIMER_PERIOD, mainDONT_BLOCK ); + /* Update the xExecutionRate variable as the rate at which this + callback is executed has to be passed into the + xAreTimerDemoTasksStillRunning() function. */ + xExecutionRate = mainERROR_CHECK_TIMER_PERIOD; + /* Just to ensure the timer period is not changed on each execution of the callback. */ lErrorAlreadyLatched = pdTRUE; @@ -437,8 +394,7 @@ void vApplicationSetupTimerInterrupt( void ) { portBASE_TYPE xStatus; const unsigned char ucTimerCounterNumber = ( unsigned char ) 0U; -//const unsigned long ulCounterValue = ( ( XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL ); -const unsigned long ulCounterValue = ( ( ( XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL ) ) * 2UL; //_RB_ there is a clock set up incorrectly somwehre, the *2 should not be required. +const unsigned long ulCounterValue = ( ( XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL ); extern void vTickISR( void *pvUnused ); /* Initialise the timer/counter. */ @@ -478,9 +434,6 @@ void vApplicationClearTimerInterrupt( void ) { unsigned long ulCSR; - /* Increment the RTOS tick - this might cause a task to unblock. */ - vTaskIncrementTick(); - /* Clear the timer interrupt */ ulCSR = XTmrCtr_GetControlStatusReg( XPAR_AXI_TIMER_0_BASEADDR, 0 ); XTmrCtr_SetControlStatusReg( XPAR_AXI_TIMER_0_BASEADDR, 0, ulCSR ); @@ -509,6 +462,21 @@ void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName of this file. */ void vApplicationIdleHook( void ) { +static long lCheckTimerStarted = pdFALSE; + + if( lCheckTimerStarted == pdFALSE ) + { + xTimerStart( xCheckTimer, mainDONT_BLOCK ); //_RB_ comment why this is done here. + lCheckTimerStarted = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +void vApplicationTickHook( void ) +{ + /* Call the periodic timer test, which tests the timer API functions that + can be called from an ISR. */ + vTimerPeriodicISRTests(); } /*-----------------------------------------------------------*/ -- 2.39.5