embeddedsw/XilinxProcessorIPLib/drivers/ttcps/examples/xttcps_low_level_example.c

326 lines
9.2 KiB
C
Raw Normal View History

/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xttcps_low_level_example.c
*
* This file contains a design example using the Triple Timer Counter hardware
* and driver in polled mode.
*
* The example generates a square wave output on the waveform out pin.
*
* @note
*
* None
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ---- ------ -------- --------------------------------------------------------
* 1.00 drg/jz 01/23/10 First release
* 3.0 pkp 12/09/14 Change TTC_NUM_DEVICES for Zynq Ultrascale MP support
*</pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xstatus.h"
#include "xttcps.h"
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are only defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define PCLK_FREQ_HZ XPAR_XTTCPS_0_CLOCK_HZ /* Input freq */
#define TTC_NUM_DEVICES 2
#define TABLE_OFFSET 6
#define MAX_LOOP_COUNT 0xFFFF
/**************************** Type Definitions *******************************/
typedef struct {
u32 OutputHz; /* The frequency the timer should output on the
waveout pin */
u8 OutputDutyCycle; /* The duty cycle of the output wave as a
percentage */
u8 PrescalerValue; /* Value of the prescaler in the Count Control
register */
} TmrCntrSetup;
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int TmrCtrLowLevelExample(u8 SettingsTableOffset);
/************************** Variable Definitions *****************************/
/*
* Convert from a 0-2 index to the correct timer counter number as defined in
* xttcps_hw.h
*/
static u32 TimerCounterBaseAddr[] = {
XPAR_XTTCPS_0_BASEADDR,
XPAR_XTTCPS_1_BASEADDR
};
/*
* A table of the actual prescaler setting based on the prescaler value from
* 0-15. The setting is 2^(prescaler value + 1). Use a table to avoid doing
* powers at run time.
* A Prescaler value of 16, means use no prescaler, or a prescaler value of 1.
*/
static u32 PrescalerSettings[] = {
2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
32768, 65536, 1
};
static TmrCntrSetup SettingsTable[] = {
/* Table offset of 0 */
{10, 50, 6},
{10, 25, 6},
{10, 75, 6},
/* Table offset of 3 */
{100, 50, 3},
{200, 25, 2},
{400, 12.5, 1},
/* Table offset of 6 */
{500, 50, 1},
{1000, 50, 0},
{5000, 50, 16},
/* Table offset of 9 */
{10000, 50, 16},
{50000, 50, 16},
{100000, 50, 16},
/* Table offset of 12 */
{500000, 50, 16},
{1000000, 50, 16},
{5000000, 50, 16},
/* Note: at greater than 1 MHz the timer reload is noticeable. */
};
#define SETTINGS_TABLE_SIZE (sizeof(SettingsTable)/sizeof(TmrCntrSetup))
/*****************************************************************************/
/**
*
* This function is the main function of the Timer/Counter example.
*
* @param None
*
* @return XST_SUCCESS to indicate success, else XST_FAILURE to indicate
* a Failure.
*
* @note None.
*
*****************************************************************************/
int main(void)
{
int Status;
xil_printf("TTC Lowlevel Example Test \r\n");
/*
* Run the Timer Counter - Low Level example.
*/
Status = TmrCtrLowLevelExample(TABLE_OFFSET);
if (Status != XST_SUCCESS) {
xil_printf("TTC Lowlevel Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran TTC Lowlevel Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function does a minimal test on the timer counter device and
* the low level driver as a design example. The purpose of this function is
* to illustrate how to use the XTtcPs low level driver.
*
*
* @param SettingsTableOffset is an offset into the settings table. This
* allows multiple counter setups to be kept and swapped easily.
*
* @return XST_SUCCESS to indicate success, else XST_FAILURE to indicate
* a Failure.
*
* @note
*
* This function contains a loop which waits for the value of a timer counter
* to change. If the hardware is not working correctly, this function may not
* return.
*
****************************************************************************/
int TmrCtrLowLevelExample(u8 SettingsTableOffset)
{
u32 RegValue;
u32 LoopCount;
u32 TmrCtrBaseAddress;
u32 IntervalValue, MatchValue;
TmrCntrSetup *CurrSetup;
/*
* Assert on the value of constants calculated above
* Because the counters are 16 bits, no value can be greater than 65535
*/
if ((SettingsTableOffset + 2) > SETTINGS_TABLE_SIZE) {
return XST_FAILURE;
}
for (LoopCount = 0; LoopCount < TTC_NUM_DEVICES; LoopCount++) {
/*
* Set the timer counter number to use
*/
TmrCtrBaseAddress = TimerCounterBaseAddr[LoopCount];
/* And get the setup for that counter
*/
CurrSetup = &SettingsTable[SettingsTableOffset + LoopCount];
/*
* Set the Clock Control Register
*/
if (16 > CurrSetup->PrescalerValue) {
/* Use the clock prescaler */
RegValue =
(CurrSetup->
PrescalerValue <<
XTTCPS_CLK_CNTRL_PS_VAL_SHIFT) &
XTTCPS_CLK_CNTRL_PS_VAL_MASK;
RegValue |= XTTCPS_CLK_CNTRL_PS_EN_MASK;
}
else {
/* Do not use the clock prescaler */
RegValue = 0;
}
XTtcPs_WriteReg(TmrCtrBaseAddress, XTTCPS_CLK_CNTRL_OFFSET,
RegValue);
/*
* Set the Interval register. This determines the frequency of
* the waveform. The counter will be reset to 0 each time this
* value is reached.
*/
IntervalValue = PCLK_FREQ_HZ /
(u32) (PrescalerSettings[CurrSetup->PrescalerValue] *
CurrSetup->OutputHz);
/*
* Make sure the value is not to large or too small
*/
if ((65535 < IntervalValue) || (4 > IntervalValue)) {
return XST_FAILURE;
}
XTtcPs_WriteReg(TmrCtrBaseAddress,
XTTCPS_INTERVAL_VAL_OFFSET, IntervalValue);
/*
* Set the Match register. This determines the duty cycle of the
* waveform. The waveform output will be toggle each time this
* value is reached.
*/
MatchValue = (IntervalValue * CurrSetup->OutputDutyCycle) / 100;
/*
* Make sure the value is not to large or too small
*/
if ((65535 < MatchValue) || (4 > MatchValue)) {
return XST_FAILURE;
}
XTtcPs_WriteReg(TmrCtrBaseAddress, XTTCPS_MATCH_0_OFFSET,
MatchValue);
/*
* Set the Counter Control Register
*/
RegValue =
~(XTTCPS_CNT_CNTRL_DIS_MASK |
XTTCPS_CNT_CNTRL_EN_WAVE_MASK) &
(XTTCPS_CNT_CNTRL_INT_MASK |
XTTCPS_CNT_CNTRL_MATCH_MASK |
XTTCPS_CNT_CNTRL_RST_MASK);
XTtcPs_WriteReg(TmrCtrBaseAddress, XTTCPS_CNT_CNTRL_OFFSET,
RegValue);
/*
* Write to the Interrupt enable register. The status flags are
* not active if this is not done.
*/
XTtcPs_WriteReg(TmrCtrBaseAddress, XTTCPS_IER_OFFSET,
XTTCPS_IXR_INTERVAL_MASK);
}
LoopCount = 0;
while (LoopCount < MAX_LOOP_COUNT) {
/*
* Read the status register for debugging
*/
RegValue =
XTtcPs_ReadReg(TmrCtrBaseAddress, XTTCPS_ISR_OFFSET);
/*
* Write the status register to clear the flags
*/
XTtcPs_WriteReg(TmrCtrBaseAddress, XTTCPS_ISR_OFFSET,
RegValue);
if (0 != (XTTCPS_IXR_INTERVAL_MASK & RegValue)) {
LoopCount++;
/*
* Count the number of output cycles so the program will
* eventually exit. Otherwise it would stay in this loop
* indefinitely.
*/
}
}
return XST_SUCCESS;
}