|
|
@ -63,6 +63,24 @@
|
|
|
|
1 tab == 4 spaces!
|
|
|
|
1 tab == 4 spaces!
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* This file initialises three timers as follows:
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* Timer 0 and Timer 1 provide the interrupts that are used with the IntQ
|
|
|
|
|
|
|
|
* standard demo tasks, which test interrupt nesting and using queues from
|
|
|
|
|
|
|
|
* interrupts. Both these interrupts operate below the maximum syscall
|
|
|
|
|
|
|
|
* interrupt priority.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* Timer 2 is a much higher frequency timer that tests the nesting of interrupts
|
|
|
|
|
|
|
|
* that execute above the maximum syscall interrupt priority.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* All the timers can nest with the tick interrupt - creating a maximum
|
|
|
|
|
|
|
|
* interrupt nesting depth of 4.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* For convenience, the high frequency timer is also used to provide the time
|
|
|
|
|
|
|
|
* base for the run time stats.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* Scheduler includes. */
|
|
|
|
/* Scheduler includes. */
|
|
|
|
#include "FreeRTOS.h"
|
|
|
|
#include "FreeRTOS.h"
|
|
|
|
|
|
|
|
|
|
|
@ -71,214 +89,173 @@
|
|
|
|
#include "IntQueue.h"
|
|
|
|
#include "IntQueue.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* Xilinx includes. */
|
|
|
|
/* Xilinx includes. */
|
|
|
|
#include "xstatus.h"
|
|
|
|
|
|
|
|
#include "xil_io.h"
|
|
|
|
|
|
|
|
#include "xil_exception.h"
|
|
|
|
|
|
|
|
#include "xttcps.h"
|
|
|
|
#include "xttcps.h"
|
|
|
|
#include "xscugic.h"
|
|
|
|
#include "xscugic.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The frequencies at which the first two timers expire are slightly offset to
|
|
|
|
|
|
|
|
ensure they don't remain synchronised. The frequency of the interrupt that
|
|
|
|
|
|
|
|
operates above the max syscall interrupt priority is 10 times faster so really
|
|
|
|
|
|
|
|
hammers the interrupt entry and exit code. */
|
|
|
|
|
|
|
|
#define tmrTIMERS_USED 3
|
|
|
|
#define tmrTIMER_0_FREQUENCY ( 2000UL )
|
|
|
|
#define tmrTIMER_0_FREQUENCY ( 2000UL )
|
|
|
|
#define tmrTIMER_1_FREQUENCY ( 2001UL )
|
|
|
|
#define tmrTIMER_1_FREQUENCY ( 2001UL )
|
|
|
|
|
|
|
|
#define tmrTIMER_2_FREQUENCY ( 20000UL )
|
|
|
|
|
|
|
|
|
|
|
|
#define TTC_TICK_DEVICE_ID XPAR_XTTCPS_0_DEVICE_ID
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#define TTC_TICK_INTR_ID XPAR_XTTCPS_0_INTR
|
|
|
|
|
|
|
|
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Constants to set the basic operating parameters.
|
|
|
|
* The single interrupt service routines that is used to service all three
|
|
|
|
* PWM_DELTA_DUTY is critical to the running time of the test. Smaller values
|
|
|
|
* timers.
|
|
|
|
* make the test run longer.
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
#define TICK_TIMER_FREQ_HZ 100 /* Tick timer counter's output frequency */
|
|
|
|
static void prvTimerHandler( void *CallBackRef );
|
|
|
|
|
|
|
|
|
|
|
|
#define TICKS_PER_CHANGE_PERIOD TICK_TIMER_FREQ_HZ /* Tick signals per update */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
#define TIMERS_USED 2
|
|
|
|
/* Hardware constants. */
|
|
|
|
|
|
|
|
static const BaseType_t xDeviceIDs[ tmrTIMERS_USED ] = { XPAR_XTTCPS_0_DEVICE_ID, XPAR_XTTCPS_1_DEVICE_ID, XPAR_XTTCPS_2_DEVICE_ID };
|
|
|
|
|
|
|
|
static const BaseType_t xInterruptIDs[ tmrTIMERS_USED ] = { XPAR_XTTCPS_0_INTR, XPAR_XTTCPS_1_INTR, XPAR_XTTCPS_2_INTR };
|
|
|
|
|
|
|
|
|
|
|
|
static void TickHandler(void *CallBackRef);
|
|
|
|
/* Timer configuration settings. */
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
uint32_t OutputHz; /* Output frequency. */
|
|
|
|
|
|
|
|
uint16_t Interval; /* Interval value. */
|
|
|
|
|
|
|
|
uint8_t Prescaler; /* Prescaler value. */
|
|
|
|
|
|
|
|
uint16_t Options; /* Option settings. */
|
|
|
|
|
|
|
|
} TmrCntrSetup;
|
|
|
|
|
|
|
|
|
|
|
|
static volatile uint8_t UpdateFlag; /* Flag to update the seconds counter */
|
|
|
|
static TmrCntrSetup xTimerSettings[ tmrTIMERS_USED ] =
|
|
|
|
static uint32_t TickCount; /* Ticker interrupts between seconds change */
|
|
|
|
{
|
|
|
|
static XTtcPs TtcPsInst[ TIMERS_USED ]; /* Timer counter instance */
|
|
|
|
{ tmrTIMER_0_FREQUENCY, 0, 0, XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE },
|
|
|
|
|
|
|
|
{ tmrTIMER_1_FREQUENCY, 0, 0, XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE },
|
|
|
|
|
|
|
|
{ tmrTIMER_2_FREQUENCY, 0, 0, XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE }
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Lower priority number means higher logical priority, so
|
|
|
|
|
|
|
|
configMAX_API_CALL_INTERRUPT_PRIORITY - 1 is above the maximum system call
|
|
|
|
|
|
|
|
interrupt priority. */
|
|
|
|
|
|
|
|
static const UBaseType_t uxInterruptPriorities[ tmrTIMERS_USED ] =
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
configMAX_API_CALL_INTERRUPT_PRIORITY + 1,
|
|
|
|
|
|
|
|
configMAX_API_CALL_INTERRUPT_PRIORITY,
|
|
|
|
|
|
|
|
configMAX_API_CALL_INTERRUPT_PRIORITY - 1
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static XTtcPs xTimerInstances[ tmrTIMERS_USED ];
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
/* Used to provide a means of ensuring the intended interrupt nesting depth is
|
|
|
|
u32 OutputHz; /* Output frequency */
|
|
|
|
actually being reached. */
|
|
|
|
u16 Interval; /* Interval value */
|
|
|
|
extern uint32_t ulPortInterruptNesting;
|
|
|
|
u8 Prescaler; /* Prescaler value */
|
|
|
|
static uint32_t ulMaxRecordedNesting = 0;
|
|
|
|
u16 Options; /* Option settings */
|
|
|
|
|
|
|
|
} TmrCntrSetup;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const TmrCntrSetup SettingsTable[ TIMERS_USED ] = { { tmrTIMER_0_FREQUENCY, 0, 0, XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE },
|
|
|
|
/* For convenience the high frequency timer increments a variable that is then
|
|
|
|
{ tmrTIMER_1_FREQUENCY, 0, 0, XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE } };
|
|
|
|
used as the time base for the run time stats. */
|
|
|
|
|
|
|
|
volatile uint32_t ulHighFrequencyTimerCounts = 0;
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t DeviceIDs[ TIMERS_USED ] = { XPAR_XTTCPS_0_DEVICE_ID, XPAR_XTTCPS_1_DEVICE_ID };
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
BaseType_t InterruptIDs[ TIMERS_USED ] = { XPAR_XTTCPS_0_INTR, XPAR_XTTCPS_1_INTR };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void vInitialiseTimerForIntQueueTest( void )
|
|
|
|
void vInitialiseTimerForIntQueueTest( void )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int Status;
|
|
|
|
BaseType_t xStatus;
|
|
|
|
TmrCntrSetup *TimerSetup;
|
|
|
|
TmrCntrSetup *pxTimerSettings;
|
|
|
|
XTtcPs *TtcPsTick;
|
|
|
|
|
|
|
|
extern XScuGic xInterruptController;
|
|
|
|
extern XScuGic xInterruptController;
|
|
|
|
BaseType_t xTimer;
|
|
|
|
BaseType_t xTimer;
|
|
|
|
XTtcPs *Timer;
|
|
|
|
XTtcPs *pxTimerInstance;
|
|
|
|
XTtcPs_Config *Config;
|
|
|
|
XTtcPs_Config *pxTimerConfiguration;
|
|
|
|
|
|
|
|
const uint8_t ucRisingEdge = 3;
|
|
|
|
|
|
|
|
|
|
|
|
for( xTimer = 0; xTimer < TIMERS_USED; xTimer++ )
|
|
|
|
for( xTimer = 0; xTimer < tmrTIMERS_USED; xTimer++ )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Look up the timer's configuration. */
|
|
|
|
|
|
|
|
pxTimerInstance = &( xTimerInstances[ xTimer ] );
|
|
|
|
|
|
|
|
pxTimerConfiguration = XTtcPs_LookupConfig( xDeviceIDs[ xTimer ] );
|
|
|
|
|
|
|
|
configASSERT( pxTimerConfiguration );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pxTimerSettings = &( xTimerSettings[ xTimer ] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Initialise the device. */
|
|
|
|
|
|
|
|
xStatus = XTtcPs_CfgInitialize( pxTimerInstance, pxTimerConfiguration, pxTimerConfiguration->BaseAddress );
|
|
|
|
|
|
|
|
if( xStatus != XST_SUCCESS )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Not sure how to do this before XTtcPs_CfgInitialize is called
|
|
|
|
|
|
|
|
as pxTimerInstance is set within XTtcPs_CfgInitialize(). */
|
|
|
|
|
|
|
|
XTtcPs_Stop( pxTimerInstance );
|
|
|
|
|
|
|
|
xStatus = XTtcPs_CfgInitialize( pxTimerInstance, pxTimerConfiguration, pxTimerConfiguration->BaseAddress );
|
|
|
|
|
|
|
|
configASSERT( xStatus == XST_SUCCESS );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Set the options. */
|
|
|
|
|
|
|
|
XTtcPs_SetOptions( pxTimerInstance, pxTimerSettings->Options );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The timer frequency is preset in the pxTimerSettings structure.
|
|
|
|
|
|
|
|
Derive the values for the other structure members. */
|
|
|
|
|
|
|
|
XTtcPs_CalcIntervalFromFreq( pxTimerInstance, pxTimerSettings->OutputHz, &( pxTimerSettings->Interval ), &( pxTimerSettings->Prescaler ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Set the interval and prescale. */
|
|
|
|
|
|
|
|
XTtcPs_SetInterval( pxTimerInstance, pxTimerSettings->Interval );
|
|
|
|
|
|
|
|
XTtcPs_SetPrescaler( pxTimerInstance, pxTimerSettings->Prescaler );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The priority must be the lowest possible. */
|
|
|
|
|
|
|
|
XScuGic_SetPriorityTriggerType( &xInterruptController, xInterruptIDs[ xTimer ], uxInterruptPriorities[ xTimer ] << portPRIORITY_SHIFT, ucRisingEdge );
|
|
|
|
|
|
|
|
|
|
|
|
TimerSetup = &( SettingsTable[ xTimer ] );
|
|
|
|
/* Connect to the interrupt controller. */
|
|
|
|
Timer = &TtcPsInst[ xTimer ];
|
|
|
|
xStatus = XScuGic_Connect( &xInterruptController, xInterruptIDs[ xTimer ], ( Xil_InterruptHandler ) prvTimerHandler, ( void * ) pxTimerInstance );
|
|
|
|
|
|
|
|
configASSERT( xStatus == XST_SUCCESS);
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Look up the configuration based on the device identifier
|
|
|
|
/* Enable the interrupt in the GIC. */
|
|
|
|
*/
|
|
|
|
XScuGic_Enable( &xInterruptController, xInterruptIDs[ xTimer ] );
|
|
|
|
Config = XTtcPs_LookupConfig(DeviceIDs[ xTimer ]);
|
|
|
|
|
|
|
|
configASSERT( Config );
|
|
|
|
/* Enable the interrupts in the timer. */
|
|
|
|
|
|
|
|
XTtcPs_EnableInterrupts( pxTimerInstance, XTTCPS_IXR_INTERVAL_MASK );
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Initialize the device
|
|
|
|
/* Start the timer. */
|
|
|
|
*/
|
|
|
|
XTtcPs_Start( pxTimerInstance );
|
|
|
|
Status = XTtcPs_CfgInitialize(Timer, Config, Config->BaseAddress);
|
|
|
|
|
|
|
|
configASSERT(Status == XST_SUCCESS);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Stop the timer first
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XTtcPs_Stop( Timer );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Set the options
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XTtcPs_SetOptions(Timer, TimerSetup->Options);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Timer frequency is preset in the TimerSetup structure,
|
|
|
|
|
|
|
|
* however, the value is not reflected in its other fields, such as
|
|
|
|
|
|
|
|
* IntervalValue and PrescalerValue. The following call will map the
|
|
|
|
|
|
|
|
* frequency to the interval and prescaler values.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XTtcPs_CalcIntervalFromFreq(Timer, TimerSetup->OutputHz,
|
|
|
|
|
|
|
|
&(TimerSetup->Interval), &(TimerSetup->Prescaler));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Set the interval and prescale
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XTtcPs_SetInterval(Timer, TimerSetup->Interval);
|
|
|
|
|
|
|
|
XTtcPs_SetPrescaler(Timer, TimerSetup->Prescaler);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Connect to the interrupt controller
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
Status = XScuGic_Connect(&xInterruptController, InterruptIDs[ xTimer ], (Xil_InterruptHandler)TickHandler, (void *)Timer);
|
|
|
|
|
|
|
|
configASSERT( Status == XST_SUCCESS);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Enable the interrupt for the Timer counter
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XScuGic_Enable(&xInterruptController, InterruptIDs[ xTimer ]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Enable the interrupts for the tick timer/counter
|
|
|
|
|
|
|
|
* We only care about the interval timeout.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XTtcPs_EnableInterrupts(Timer, XTTCPS_IXR_INTERVAL_MASK);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Start the tick timer/counter
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XTtcPs_Start(Timer);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
void vT2InterruptHandler( void )
|
|
|
|
static void prvTimerHandler( void *pvCallBackRef )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
portEND_SWITCHING_ISR( xFirstTimerHandler() );
|
|
|
|
uint32_t ulInterruptStatus;
|
|
|
|
}
|
|
|
|
XTtcPs *pxTimer = ( XTtcPs * ) pvCallBackRef;
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
BaseType_t xYieldRequired;
|
|
|
|
|
|
|
|
|
|
|
|
void vT3InterruptHandler( void )
|
|
|
|
/* Read the interrupt status, then write it back to clear the interrupt. */
|
|
|
|
{
|
|
|
|
ulInterruptStatus = XTtcPs_GetInterruptStatus( pxTimer );
|
|
|
|
portEND_SWITCHING_ISR( xSecondTimerHandler() );
|
|
|
|
XTtcPs_ClearInterruptStatus( pxTimer, ulInterruptStatus );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
volatile uint32_t ulTimer1Count = 0, ulTimer2Count = 0;
|
|
|
|
/* Only one interrupt event type is expected. */
|
|
|
|
|
|
|
|
configASSERT( ( XTTCPS_IXR_INTERVAL_MASK & ulInterruptStatus ) != 0 );
|
|
|
|
|
|
|
|
|
|
|
|
static void TickHandler(void *CallBackRef)
|
|
|
|
/* Check the device ID to know which IntQueue demo to call. */
|
|
|
|
{
|
|
|
|
if( pxTimer->Config.DeviceId == xDeviceIDs[ 0 ] )
|
|
|
|
uint32_t StatusEvent;
|
|
|
|
{
|
|
|
|
XTtcPs *pxTtcPs = (XTtcPs *)CallBackRef;
|
|
|
|
xYieldRequired = xFirstTimerHandler();
|
|
|
|
/*
|
|
|
|
}
|
|
|
|
* Read the interrupt status, then write it back to clear the interrupt.
|
|
|
|
else if( pxTimer->Config.DeviceId == xDeviceIDs[ 1 ] )
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
StatusEvent = XTtcPs_GetInterruptStatus(pxTtcPs);
|
|
|
|
xYieldRequired = xSecondTimerHandler();
|
|
|
|
XTtcPs_ClearInterruptStatus(pxTtcPs, StatusEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
if (0 != (XTTCPS_IXR_INTERVAL_MASK & StatusEvent)) {
|
|
|
|
{
|
|
|
|
if( pxTtcPs->Config.DeviceId == DeviceIDs[ 0 ] )
|
|
|
|
/* The high frequency timer is also used to generate the time base for
|
|
|
|
{
|
|
|
|
the run time state. */
|
|
|
|
ulTimer1Count++;
|
|
|
|
ulHighFrequencyTimerCounts++;
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
/* Latch the highest interrupt nesting count detected. */
|
|
|
|
|
|
|
|
if( ulPortInterruptNesting > ulMaxRecordedNesting )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ulTimer2Count++;
|
|
|
|
ulMaxRecordedNesting = ulPortInterruptNesting;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TickCount++;
|
|
|
|
|
|
|
|
|
|
|
|
xYieldRequired = pdFALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* If xYieldRequired is not pdFALSE then calling either xFirstTimerHandler()
|
|
|
|
int SetupTimer(int DeviceID)
|
|
|
|
or xSecondTimerHandler() resulted in a task leaving the blocked state and
|
|
|
|
{
|
|
|
|
the task that left the blocked state had a priority higher than the currently
|
|
|
|
int Status;
|
|
|
|
running task (the task this interrupt interrupted) - so a context switch
|
|
|
|
XTtcPs_Config *Config;
|
|
|
|
should be performed so the interrupt returns directly to the higher priority
|
|
|
|
XTtcPs *Timer;
|
|
|
|
task. xYieldRequired is tested inside the following macro. */
|
|
|
|
TmrCntrSetup *TimerSetup;
|
|
|
|
portYIELD_FROM_ISR( xYieldRequired );
|
|
|
|
|
|
|
|
|
|
|
|
TimerSetup = &SettingsTable;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Timer = &TtcPsInst;
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Stop the timer first
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XTtcPs_Stop( &TtcPsInst );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Look up the configuration based on the device identifier
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
Config = XTtcPs_LookupConfig(DeviceIDs[ DeviceID ]);
|
|
|
|
|
|
|
|
configASSERT( Config );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Initialize the device
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
Status = XTtcPs_CfgInitialize(Timer, Config, Config->BaseAddress);
|
|
|
|
|
|
|
|
configASSERT(Status == XST_SUCCESS);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Set the options
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XTtcPs_SetOptions(Timer, TimerSetup->Options);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Timer frequency is preset in the TimerSetup structure,
|
|
|
|
|
|
|
|
* however, the value is not reflected in its other fields, such as
|
|
|
|
|
|
|
|
* IntervalValue and PrescalerValue. The following call will map the
|
|
|
|
|
|
|
|
* frequency to the interval and prescaler values.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XTtcPs_CalcIntervalFromFreq(Timer, TimerSetup->OutputHz,
|
|
|
|
|
|
|
|
&(TimerSetup->Interval), &(TimerSetup->Prescaler));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Set the interval and prescale
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
XTtcPs_SetInterval(Timer, TimerSetup->Interval);
|
|
|
|
|
|
|
|
XTtcPs_SetPrescaler(Timer, TimerSetup->Prescaler);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return XST_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|