Hi,
I'm trying to generate PWM signals using AXI timers but right now I'm having some difficulty even getting just a square wave output from the timer so I'm hoping someone can help me with that first.
My hardware setup follows the instructions in Zynq Book Exercise 2D, with the timer & Zedboard buttons generating interrupts concatenated together, except that I've added three additional ports connected to the AXI timer outputs generateout0, generateout1, and pwm0.
My code also follows that example, except that I've modified the timer options setup by adding the XTC_EXT_COMPARE_OPTION into the following line:
XTmrCtr_SetOptions(&TMRInst, 0, XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_EXT_COMPARE_OPTION);
My constraint file:
set_property PACKAGE_PIN W8 [get_ports pmod_jb4]
set_property PACKAGE_PIN AA9 [get_ports pmod_ja4]
set_property PACKAGE_PIN Y10 [get_ports pmod_ja3]
set_property IOSTANDARD LVCMOS33 [get_ports pmod_ja4]
set_property IOSTANDARD LVCMOS33 [get_ports pmod_jb4]
set_property IOSTANDARD LVCMOS33 [get_ports pmod_ja3]
My code:
#include "xparameters.h"
#include "xgpio.h"
#include "xtmrctr.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xil_printf.h"
// Parameter definitions
#define INTC_DEVICE_ID ttXPAR_PS7_SCUGIC_0_DEVICE_ID
#define TMR_DEVICE_IDttXPAR_TMRCTR_0_DEVICE_ID
#define BTNS_DEVICE_IDttXPAR_AXI_GPIO_0_DEVICE_ID
#define LEDS_DEVICE_IDttXPAR_AXI_GPIO_1_DEVICE_ID
#define INTC_GPIO_INTERRUPT_ID XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR
#define INTC_TMR_INTERRUPT_ID XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR
#define BTN_INT tttXGPIO_IR_CH1_MASK
#define TMR_LOADttt0xFFFE7961
XGpio LEDInst, BTNInst;
XScuGic INTCInst;
XTmrCtr TMRInst;
static int led_data;
static int btn_value;
static int tmr_count;
//----------------------------------------------------
// PROTOTYPE FUNCTIONS
//----------------------------------------------------
static void BTN_Intr_Handler(void *baseaddr_p);
static void TMR_Intr_Handler(void *baseaddr_p);
static int InterruptSystemSetup(XScuGic *XScuGicInstancePtr);
static int IntcInitFunction(u16 DeviceId, XTmrCtr *TmrInstancePtr, XGpio *GpioInstancePtr);
//----------------------------------------------------
// INTERRUPT HANDLER FUNCTIONS
// - called by the timer, button interrupt, performs
// - LED flashing
//----------------------------------------------------
void BTN_Intr_Handler(void *InstancePtr)
{
t// Disable GPIO interrupts
tXGpio_InterruptDisable(&BTNInst, BTN_INT);
t// Ignore additional button presses
tif ((XGpio_InterruptGetStatus(&BTNInst) & BTN_INT) !=
tttBTN_INT) {
tttreturn;
tt}
tbtn_value = XGpio_DiscreteRead(&BTNInst, 1);
t// Increment counter based on button value
t// Reset if centre button pressed
tif(btn_value != 1) led_data = led_data + btn_value;
telse led_data = 0;
XGpio_DiscreteWrite(&LEDInst, 1, led_data);
(void)XGpio_InterruptClear(&BTNInst, BTN_INT);
// Enable GPIO interrupts
XGpio_InterruptEnable(&BTNInst, BTN_INT);
}
void TMR_Intr_Handler(void *data)
{
tif (XTmrCtr_IsExpired(&TMRInst,0)){
ttXTmrCtr_Stop(&TMRInst,0);
tt// Once timer has expired 3 times, stop, increment counter
tt// reset timer and start running again
tt//if(tmr_count == 3){
tt//ttmr_count = 0;
tttled_data++;
tttXGpio_DiscreteWrite(&LEDInst, 1, led_data);
tt//}
tt//else tmr_count++;
tXTmrCtr_Reset(&TMRInst,0);
tXTmrCtr_Start(&TMRInst,0);
t}
}
//----------------------------------------------------
// MAIN FUNCTION
//----------------------------------------------------
int main (void)
{
int status;
//----------------------------------------------------
// INITIALIZE THE PERIPHERALS & SET DIRECTIONS OF GPIO
//----------------------------------------------------
// Initialise LEDs
status = XGpio_Initialize(&LEDInst, LEDS_DEVICE_ID);
if(status != XST_SUCCESS) return XST_FAILURE;
// Initialise Push Buttons
status = XGpio_Initialize(&BTNInst, BTNS_DEVICE_ID);
if(status != XST_SUCCESS) return XST_FAILURE;
// Set LEDs direction to outputs
XGpio_SetDataDirection(&LEDInst, 1, 0x00);
// Set all buttons direction to inputs
XGpio_SetDataDirection(&BTNInst, 1, 0xFF);
//----------------------------------------------------
// SETUP THE TIMER
//----------------------------------------------------
status = XTmrCtr_Initialize(&TMRInst, TMR_DEVICE_ID);
if(status != XST_SUCCESS) return XST_FAILURE;
XTmrCtr_SetHandler(&TMRInst, TMR_Intr_Handler, &TMRInst);
XTmrCtr_SetResetValue(&TMRInst, 0, TMR_LOAD);
XTmrCtr_SetOptions(&TMRInst, 0, XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_EXT_COMPARE_OPTION);
//XTC_INT_MODE_OPTION
// Initialize interrupt controller
status = IntcInitFunction(INTC_DEVICE_ID, &TMRInst, &BTNInst);
if(status != XST_SUCCESS) return XST_FAILURE;
XTmrCtr_Start(&TMRInst, 0);
while(1);
return 0;
}
//----------------------------------------------------
// INITIAL SETUP FUNCTIONS
//----------------------------------------------------
int InterruptSystemSetup(XScuGic *XScuGicInstancePtr)
{
t// Enable interrupt
tXGpio_InterruptEnable(&BTNInst, BTN_INT);
tXGpio_InterruptGlobalEnable(&BTNInst);
tXil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
ttt t t t t t (Xil_ExceptionHandler)XScuGic_InterruptHandler,
ttt t t t t t XScuGicInstancePtr);
tXil_ExceptionEnable();
treturn XST_SUCCESS;
}
int IntcInitFunction(u16 DeviceId, XTmrCtr *TmrInstancePtr, XGpio *GpioInstancePtr)
{
tXScuGic_Config *IntcConfig;
tint status;
t// Interrupt controller initialisation
tIntcConfig = XScuGic_LookupConfig(DeviceId);
tstatus = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);
tif(status != XST_SUCCESS) return XST_FAILURE;
t// Call to interrupt setup
tstatus = InterruptSystemSetup(&INTCInst);
tif(status != XST_SUCCESS) return XST_FAILURE;
t
t// Connect GPIO interrupt to handler
tstatus = XScuGic_Connect(&INTCInst,
ttttt t t INTC_GPIO_INTERRUPT_ID,
ttttt t t (Xil_ExceptionHandler)BTN_Intr_Handler,
ttttt t t (void *)GpioInstancePtr);
tif(status != XST_SUCCESS) return XST_FAILURE;
t// Connect timer interrupt to handler
tstatus = XScuGic_Connect(&INTCInst,
ttttttt INTC_TMR_INTERRUPT_ID,
ttttttt (Xil_ExceptionHandler)TMR_Intr_Handler,
ttttttt (void *)TmrInstancePtr);
tif(status != XST_SUCCESS) return XST_FAILURE;
t// Enable GPIO interrupts interrupt
tXGpio_InterruptEnable(GpioInstancePtr, 1);
tXGpio_InterruptGlobalEnable(GpioInstancePtr);
t// Enable GPIO and timer interrupts in the controller
tXScuGic_Enable(&INTCInst, INTC_GPIO_INTERRUPT_ID);
t
tXScuGic_Enable(&INTCInst, INTC_TMR_INTERRUPT_ID);
t
treturn XST_SUCCESS;
}