Continue commenting the new MicroBlaze demo.

pull/4/head
Richard Barry 14 years ago
parent 0e02cc56b1
commit e46b2a304f

@ -48,6 +48,7 @@ IF EXIST FreeRTOS_Source Goto END
copy ..\..\..\Common\minimal\sp_flop.c Demo_Source copy ..\..\..\Common\minimal\sp_flop.c Demo_Source
copy ..\..\..\Common\minimal\flash.c Demo_Source copy ..\..\..\Common\minimal\flash.c Demo_Source
copy ..\..\..\Common\minimal\comtest_strings.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. REM Copy the common demo file headers.
copy ..\..\..\Common\include\dynamic.h Demo_Source\include 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\comtest_strings.h Demo_Source\include
copy ..\..\..\Common\include\serial.h Demo_Source\include copy ..\..\..\Common\include\serial.h Demo_Source\include
copy ..\..\..\Common\include\comtest.h Demo_Source\include copy ..\..\..\Common\include\comtest.h Demo_Source\include
copy ..\..\..\Common\include\TimerDemo.h Demo_Source\include
: END : END

@ -77,10 +77,10 @@
*----------------------------------------------------------*/ *----------------------------------------------------------*/
#define configUSE_PREEMPTION 1 #define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 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 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 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 configTOTAL_HEAP_SIZE ( ( size_t ) ( 64 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 10 ) #define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 0 #define configUSE_TRACE_FACILITY 0

@ -311,8 +311,6 @@ portBASE_TYPE xListWasEmpty;
/* Just to avoid compiler warnings. */ /* Just to avoid compiler warnings. */
( void ) pvParameters; ( void ) pvParameters;
vTaskDelay( 2 );
for( ;; ) for( ;; )
{ {
/* Query the timers list to see if it contains any timers, and if so, /* Query the timers list to see if it contains any timers, and if so,

@ -113,11 +113,8 @@
#include "queue.h" #include "queue.h"
#include "timers.h" #include "timers.h"
/* BSP includes. *///_RB_ which of these can be removed? /* BSP includes. */
#include "xenv_standalone.h"
#include "xtmrctr.h" #include "xtmrctr.h"
#include "xil_exception.h"
#include "microblaze_exceptions_g.h"
#include "xgpio.h" #include "xgpio.h"
/* Priorities at which the tasks are created. */ /* Priorities at which the tasks are created. */
@ -196,6 +193,13 @@ static const unsigned long ulGPIOOutputChannel = 1UL, ulGPIOInputChannel = 1UL;
int main( void ) 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. */ /* Configure the interrupt controller, LED outputs and button inputs. */
prvSetupHardware(); prvSetupHardware();
@ -380,10 +384,6 @@ const unsigned char ucSetToOutput = 0U;
} }
configASSERT( ( xStatus == pdPASS ) ); 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 /* This is an application defined callback function used to install the tick
interrupt handler. It is provided as an application callback because the kernel 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 will run on lots of different MicroBlaze and FPGA configurations - not all of

@ -52,28 +52,20 @@
*/ */
/* **************************************************************************** /* ****************************************************************************
* This project includes a lot of tasks and tests and is therefore complex. * 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 * If you would prefer a much simpler project to get started with, then select
* the 'Blinky' build configuration within the Embedded Workbench IDE. * the 'Blinky' build configuration within the SDK Eclipse IDE.
* **************************************************************************** * ****************************************************************************
* *
* Creates all the demo application tasks, then starts the scheduler. The web * main() creates all the demo application tasks, then starts the scheduler.
* documentation provides more details of the standard demo application tasks, * The web documentation provides more details of the standard demo application
* which provide no particular functionality but do provide a good example of * tasks, which provide no particular functionality, but do provide a good
* how to use the FreeRTOS API. The tasks defined in flop.c are included in the * example of how to use the FreeRTOS API.
* set of standard demo tasks to ensure the floating point unit gets some
* exercise.
* *
* In addition to the standard demo tasks, the following tasks and tests are * In addition to the standard demo tasks, the following tasks and tests are
* defined and/or created within this file: * defined and/or created within this file:
* *
* Webserver ("uIP") task - This serves a number of dynamically generated WEB * Webserver ("lwIP") task - TBD _RB_
* 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.
* *
* "Reg test" tasks - These fill the registers with known values, then check * "Reg test" tasks - These fill the registers with known values, then check
* that each register still contains its expected value. Each task uses * 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 * 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 * 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 * 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 * error has occurred. The nature of the reg test tasks necessitates that they
* are written in assembly code. * are written in assembly code.
* *
* "Check" task - This only executes every five seconds but has a high priority * "Check" timer - The check timer period is initially set to five seconds.
* to ensure it gets processor time. Its main function is to check that all the * The check timer callback function checks that all the standard demo tasks are
* standard demo tasks are still operational. While no errors have been * functioning as expected, without error. If an error is discovered in any
* discovered the check task will toggle LED 5 every 5 seconds - the toggle * standard demo task, then the check timer period is shortened to 200ms. The
* rate increasing to 200ms being a visual indication that at least one task has * check timer callback function also toggles an LED each time it is called.
* reported unexpected behaviour. * 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 * This file also includes example implementations of the vApplicationTickHook(),
* generated using a timer - the interrupt is assigned a priority above * vApplicationIdleHook(), vApplicationStackOverflowHook(),
* configMAX_SYSCALL_INTERRUPT_PRIORITY so should not be effected by anything * vApplicationMallocFailedHook(), vApplicationClearTimerInterrupt(), and
* the kernel is doing. The frequency and priority of the interrupt, in * vApplicationSetupTimerInterrupt() callback (hook) functions.
* 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).
*/
/* Standard includes. */ /* Standard includes. */
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
/* BSP includes. */ /* BSP includes. */
#include "xenv_standalone.h"
#include "xtmrctr.h" #include "xtmrctr.h"
#include "xil_exception.h"
#include "microblaze_exceptions_g.h"
#include "xgpio.h"
/* Kernel includes. */ /* Kernel includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
@ -150,8 +120,7 @@
#include "flop.h" #include "flop.h"
#include "dynamic.h" #include "dynamic.h"
#include "comtest_strings.h" #include "comtest_strings.h"
#include "TimerDemo.h"
#define xPrintf( x )
/* Priorities at which the tasks are created. */ /* Priorities at which the tasks are created. */
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 ) #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. */ baud rate parameter. */
#define mainCOM_TEST_BAUD_RATE ( XPAR_RS232_UART_1_BAUDRATE ) #define mainCOM_TEST_BAUD_RATE ( XPAR_RS232_UART_1_BAUDRATE )
#define mainTIMER_TEST_PERIOD ( 20 )
/* /*
* vApplicationMallocFailedHook() will only be called if * vApplicationMallocFailedHook() will only be called if
* configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook * 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 ); 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 ) 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. */ /* Configure the interrupt controller, LED outputs and button inputs. */
prvSetupHardware(); prvSetupHardware();
@ -270,9 +243,6 @@ int main( void )
xTaskCreate( vRegisterTest1, ( const signed char * const ) "RegTst1", configMINIMAL_STACK_SIZE, ( void * ) 0, tskIDLE_PRIORITY, NULL ); 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 ); 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. */ /* Create the standard demo tasks. */
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
vCreateBlockTimeTasks(); vCreateBlockTimeTasks();
@ -283,6 +253,8 @@ int main( void )
vStartQueuePeekTasks(); vStartQueuePeekTasks();
vStartRecursiveMutexTasks(); vStartRecursiveMutexTasks();
vStartComTestStringsTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED ); 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 /* Note - the set of standard demo tasks contains two versions of
vStartMathTasks.c. One is defined in flop.c, and uses double precision 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. */ until after the scheduler has been started. */
xCheckTimer = xTimerCreate( ( const signed char * ) "Check timer", mainNO_ERROR_CHECK_TIMER_PERIOD, pdTRUE, ( void * ) 0, vCheckTimerCallback ); 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. */ /* Start the tasks running. */
vTaskStartScheduler(); vTaskStartScheduler();
@ -327,6 +293,7 @@ static void vCheckTimerCallback( xTimerHandle xTimer )
extern unsigned long ulRegTest1CycleCount, ulRegTest2CycleCount; extern unsigned long ulRegTest1CycleCount, ulRegTest2CycleCount;
static volatile unsigned long ulLastRegTest1CycleCount = 0UL, ulLastRegTest2CycleCount = 0UL; static volatile unsigned long ulLastRegTest1CycleCount = 0UL, ulLastRegTest2CycleCount = 0UL;
static long lErrorAlreadyLatched = pdFALSE; static long lErrorAlreadyLatched = pdFALSE;
portTickType xExecutionRate = mainNO_ERROR_CHECK_TIMER_PERIOD;
/* This is the callback function used by the 'check' timer, as described /* This is the callback function used by the 'check' timer, as described
at the top of this file. */ 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 rate at which mainCHECK_LED flashes to give visual feedback that an error
has occurred. */ has occurred. */
pcStatusMessage = "Error: GenQueue"; pcStatusMessage = "Error: GenQueue";
xPrintf( pcStatusMessage );
} }
else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
if( xAreQueuePeekTasksStillRunning() != pdTRUE )
{ {
pcStatusMessage = "Error: QueuePeek\r\n"; pcStatusMessage = "Error: QueuePeek\r\n";
xPrintf( pcStatusMessage );
} }
else if( xAreBlockingQueuesStillRunning() != pdTRUE )
if( xAreBlockingQueuesStillRunning() != pdTRUE )
{ {
pcStatusMessage = "Error: BlockQueue\r\n"; pcStatusMessage = "Error: BlockQueue\r\n";
xPrintf( pcStatusMessage );
} }
else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
{ {
pcStatusMessage = "Error: BlockTime\r\n"; pcStatusMessage = "Error: BlockTime\r\n";
xPrintf( pcStatusMessage );
} }
else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
if( xAreSemaphoreTasksStillRunning() != pdTRUE )
{ {
pcStatusMessage = "Error: SemTest\r\n"; pcStatusMessage = "Error: SemTest\r\n";
xPrintf( pcStatusMessage );
} }
else if( xArePollingQueuesStillRunning() != pdTRUE )
if( xArePollingQueuesStillRunning() != pdTRUE )
{ {
pcStatusMessage = "Error: PollQueue\r\n"; pcStatusMessage = "Error: PollQueue\r\n";
xPrintf( pcStatusMessage );
} }
else if( xIsCreateTaskStillRunning() != pdTRUE )
if( xIsCreateTaskStillRunning() != pdTRUE )
{ {
pcStatusMessage = "Error: Death\r\n"; pcStatusMessage = "Error: Death\r\n";
xPrintf( pcStatusMessage );
} }
else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
{ {
pcStatusMessage = "Error: RecMutex\r\n"; pcStatusMessage = "Error: RecMutex\r\n";
xPrintf( pcStatusMessage );
} }
else if( xAreMathsTaskStillRunning() != pdPASS )
if( xAreMathsTaskStillRunning() != pdPASS )
{ {
pcStatusMessage = "Error: Flop\r\n"; pcStatusMessage = "Error: Flop\r\n";
xPrintf( pcStatusMessage );
} }
else if( xAreComTestTasksStillRunning() != pdPASS )
if( xAreComTestTasksStillRunning() != pdPASS )
{ {
pcStatusMessage = "Error: Comtest\r\n"; pcStatusMessage = "Error: Comtest\r\n";
xPrintf( pcStatusMessage );
} }
else if( xAreDynamicPriorityTasksStillRunning() != pdPASS )
/* Check the reg test tasks are still cycling. They will stop incrementing
their loop counters if they encounter an error. */
if( ulRegTest1CycleCount == ulLastRegTest1CycleCount )
{ {
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"; pcStatusMessage = "Error: RegTest1\r\n";
xPrintf( pcStatusMessage );
} }
else if( ulRegTest2CycleCount == ulLastRegTest2CycleCount )
if( ulRegTest2CycleCount == ulLastRegTest2CycleCount )
{ {
pcStatusMessage = "Error: RegTest2\r\n"; pcStatusMessage = "Error: RegTest2\r\n";
xPrintf( pcStatusMessage );
} }
ulLastRegTest1CycleCount = ulRegTest1CycleCount; ulLastRegTest1CycleCount = ulRegTest1CycleCount;
@ -425,6 +377,11 @@ static long lErrorAlreadyLatched = pdFALSE;
This is called from a timer callback so must not attempt to block. */ This is called from a timer callback so must not attempt to block. */
xTimerChangePeriod( xTimer, mainERROR_CHECK_TIMER_PERIOD, mainDONT_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 /* Just to ensure the timer period is not changed on each execution
of the callback. */ of the callback. */
lErrorAlreadyLatched = pdTRUE; lErrorAlreadyLatched = pdTRUE;
@ -437,8 +394,7 @@ void vApplicationSetupTimerInterrupt( void )
{ {
portBASE_TYPE xStatus; portBASE_TYPE xStatus;
const unsigned char ucTimerCounterNumber = ( unsigned char ) 0U; 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 );
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.
extern void vTickISR( void *pvUnused ); extern void vTickISR( void *pvUnused );
/* Initialise the timer/counter. */ /* Initialise the timer/counter. */
@ -478,9 +434,6 @@ void vApplicationClearTimerInterrupt( void )
{ {
unsigned long ulCSR; unsigned long ulCSR;
/* Increment the RTOS tick - this might cause a task to unblock. */
vTaskIncrementTick();
/* Clear the timer interrupt */ /* Clear the timer interrupt */
ulCSR = XTmrCtr_GetControlStatusReg( XPAR_AXI_TIMER_0_BASEADDR, 0 ); ulCSR = XTmrCtr_GetControlStatusReg( XPAR_AXI_TIMER_0_BASEADDR, 0 );
XTmrCtr_SetControlStatusReg( XPAR_AXI_TIMER_0_BASEADDR, 0, ulCSR ); XTmrCtr_SetControlStatusReg( XPAR_AXI_TIMER_0_BASEADDR, 0, ulCSR );
@ -509,6 +462,21 @@ void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName
of this file. */ of this file. */
void vApplicationIdleHook( void ) 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();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

Loading…
Cancel
Save