/** * * Starts the specified timer counter of the device such that it starts running. * The timer counter is reset before it is started and the reset value is * loaded into the timer counter. * * If interrupt mode is specified in the options, it is necessary for the caller * to connect the interrupt handler of the timer/counter to the interrupt source, * typically an interrupt controller, and enable the interrupt within the * interrupt controller. * * @param InstancePtr is a pointer to the XTmrCtr instance. * @param TmrCtrNumber is the timer counter of the device to operate on. * Each device may contain multiple timer counters. The timer * number is a zero based number with a range of * 0 - (XTC_DEVICE_TIMER_COUNT - 1). * * @return None. * * @note None. * ******************************************************************************/ void XTmrCtr_Start(XTmrCtr * InstancePtr, u8 TmrCtrNumber) { u32 ControlStatusReg; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Read the current register contents such that only the necessary bits * of the register are modified in the following operations */ ControlStatusReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET); /* * Reset the timer counter such that it reloads from the compare * register and the interrupt is cleared simultaneously, the interrupt * can only be cleared after reset such that the interrupt condition is * cleared */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, XTC_CSR_LOAD_MASK); /* * Remove the reset condition such that the timer counter starts running * with the value loaded from the compare register */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, ControlStatusReg | XTC_CSR_ENABLE_TMR_MASK); }
/** * * Stops the timer counter by disabling it. * * It is the callers' responsibility to disconnect the interrupt handler of the * timer_counter from the interrupt source, typically an interrupt controller, * and disable the interrupt within the interrupt controller. * * @param InstancePtr is a pointer to the XTmrCtr instance. * @param TmrCtrNumber is the timer counter of the device to operate on. * Each device may contain multiple timer counters. The timer * number is a zero based number with a range of * 0 - (XTC_DEVICE_TIMER_COUNT - 1). * * @return None. * * @note None. * ******************************************************************************/ void XTmrCtr_Stop(XTmrCtr * InstancePtr, u8 TmrCtrNumber) { u32 ControlStatusReg; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Read the current register contents */ ControlStatusReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET); /* * Disable the timer counter such that it's not running */ ControlStatusReg &= ~(XTC_CSR_ENABLE_TMR_MASK); /* * Write out the updated value to the actual register. */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, ControlStatusReg); /* * Indicate that the timer is stopped */ if (TmrCtrNumber == 0) { InstancePtr->IsStartedTmrCtr0 = 0; } else { InstancePtr->IsStartedTmrCtr1 = 0; } }
/** * * Set the reset value for the specified timer counter. This is the value * that is loaded into the timer counter when it is reset. This value is also * loaded when the timer counter is started. * * @param InstancePtr is a pointer to the XTmrCtr instance. * @param TmrCtrNumber is the timer counter of the device to operate on. * Each device may contain multiple timer counters. The timer * number is a zero based number with a range of * 0 - (XTC_DEVICE_TIMER_COUNT - 1). * @param ResetValue contains the value to be used to reset the timer * counter. * * @return None. * * @note None. * ******************************************************************************/ void XTmrCtr_SetResetValue(XTmrCtr * InstancePtr, u8 TmrCtrNumber, u32 ResetValue) { Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TLR_OFFSET, ResetValue); }
void timer_handler() { Xuint32 ControlStatusReg; ControlStatusReg = XTimerCtr_ReadReg(Timer_tmrctr.BaseAddress, 0, XTC_TCSR_OFFSET); count++; onLED(count); XTmrCtr_WriteReg(Timer_tmrctr.BaseAddress, 0, XTC_TCSR_OFFSET, ControlStatusReg |XTC_CSR_INT_OCCURED_MASK); }
/** * * Resets the specified timer counter of the device. A reset causes the timer * counter to set it's value to the reset value. * * @param InstancePtr is a pointer to the XTmrCtr instance. * @param TmrCtrNumber is the timer counter of the device to operate on. * Each device may contain multiple timer counters. The timer * number is a zero based number with a range of * 0 - (XTC_DEVICE_TIMER_COUNT - 1). * * @return None. * * @note None. * ******************************************************************************/ void XTmrCtr_Reset(XTmrCtr * InstancePtr, u8 TmrCtrNumber) { u32 CounterControlReg; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Read current contents of the register so it won't be destroyed */ CounterControlReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET); /* * Reset the timer by toggling the reset bit in the register */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, CounterControlReg | XTC_CSR_LOAD_MASK); XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, CounterControlReg); }
/** * (Re-)initialzes all timer counters which aren't started already. * * @param InstancePtr is a pointer to the XTmrCtr instance. * * @return * - XST_SUCCESS if at least one timer counter is stopped. * - XST_DEVICE_IS_STARTED otherwise. * * @note None. * ******************************************************************************/ int XTmrCtr_InitHw(XTmrCtr *InstancePtr) { int Status = XST_DEVICE_IS_STARTED; u8 TmrIndex; u32 TmrCtrStarted[XTC_DEVICE_TIMER_COUNT]; /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); TmrCtrStarted[0] = InstancePtr->IsStartedTmrCtr0; TmrCtrStarted[1] = InstancePtr->IsStartedTmrCtr1; for (TmrIndex = 0; TmrIndex < XTC_DEVICE_TIMER_COUNT; TmrIndex++) { /* Only initialize timers counters which aren't started. */ if (TmrCtrStarted[TmrIndex] == XIL_COMPONENT_IS_STARTED) { continue; } /* Set the compare register to 0. */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrIndex, XTC_TLR_OFFSET, 0); /* Reset the timer and the interrupt. */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrIndex, XTC_TCSR_OFFSET, XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK); /* Release the reset. */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrIndex, XTC_TCSR_OFFSET, 0); /* Indicate that at least one timer is not running and has been * initialized. */ Status = XST_SUCCESS; } return Status; }
/** * * Enables the specified options for the specified timer counter. This function * sets the options without regard to the current options of the driver. To * prevent a loss of the current options, the user should call * XTmrCtr_GetOptions() prior to this function and modify the retrieved options * to pass into this function to prevent loss of the current options. * * @param InstancePtr is a pointer to the XTmrCtr instance. * @param TmrCtrNumber is the timer counter of the device to operate on. * Each device may contain multiple timer counters. The timer * number is a zero based number with a range of * 0 - (XTC_DEVICE_TIMER_COUNT - 1). * @param Options contains the desired options to be set or cleared. * Setting the option to '1' enables the option, clearing the to * '0' disables the option. The options are bit masks such that * multiple options may be set or cleared. The options are * described in xtmrctr.h. * * @return None. * * @note None. * ******************************************************************************/ void XTmrCtr_SetOptions(XTmrCtr * InstancePtr, u8 TmrCtrNumber, u32 Options) { u32 CounterControlReg = 0; u32 Index; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Loop through the Options table, turning the enable on or off * depending on whether the bit is set in the incoming Options flag. */ for (Index = 0; Index < XTC_NUM_OPTIONS; Index++) { if (Options & OptionsTable[Index].Option) { /* * Turn the option on */ CounterControlReg |= OptionsTable[Index].Mask; } else { /* * Turn the option off */ CounterControlReg &= ~OptionsTable[Index].Mask; } } /* * Write out the updated value to the actual register */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, CounterControlReg); }
/** * * Initializes a specific timer/counter instance/driver. Initialize fields of * the XTmrCtr structure, then reset the timer/counter.If a timer is already * running then it is not initialized. * * * @param InstancePtr is a pointer to the XTmrCtr instance. * @param DeviceId is the unique id of the device controlled by this * XTmrCtr component. Passing in a device id associates the * generic XTmrCtr component to a specific device, as chosen by * the caller or application developer. * * @return * - XST_SUCCESS if initialization was successful * - XST_DEVICE_IS_STARTED if the device has already been started * - XST_DEVICE_NOT_FOUND if the device doesn't exist * * @note None. * ******************************************************************************/ int XTmrCtr_Initialize(XTmrCtr * InstancePtr, u16 DeviceId) { XTmrCtr_Config *TmrCtrConfigPtr; int TmrCtrNumber; int TmrCtrLowIndex = 0; int TmrCtrHighIndex = XTC_DEVICE_TIMER_COUNT; Xil_AssertNonvoid(InstancePtr != NULL); /* * If both the timers have already started, disallow the initialize and * return a status indicating it is started. This allows the user to stop * the device and reinitialize, but prevents a user from inadvertently * initializing. * In case one of the timers has not started then that particular timer * will be initialized */ if ((InstancePtr->IsStartedTmrCtr0 == XIL_COMPONENT_IS_STARTED) && (InstancePtr->IsStartedTmrCtr1 == XIL_COMPONENT_IS_STARTED)) { return XST_DEVICE_IS_STARTED; } /* * Ensure that only the timer which is NOT started can be initialized */ if ((InstancePtr->IsStartedTmrCtr0 == XIL_COMPONENT_IS_STARTED)) { TmrCtrLowIndex = 1; } else if ((InstancePtr->IsStartedTmrCtr1 == XIL_COMPONENT_IS_STARTED)) { TmrCtrHighIndex = 1; } else { InstancePtr->IsStartedTmrCtr0 = 0; InstancePtr->IsStartedTmrCtr1 = 0; } /* * Lookup the device configuration in the temporary CROM table. Use this * configuration info down below when initializing this component. */ TmrCtrConfigPtr = XTmrCtr_LookupConfig(DeviceId); if (TmrCtrConfigPtr == (XTmrCtr_Config *) NULL) { return XST_DEVICE_NOT_FOUND; } /* * Set some default values, including setting the callback * handlers to stubs. */ InstancePtr->BaseAddress = TmrCtrConfigPtr->BaseAddress; InstancePtr->Handler = NULL; InstancePtr->CallBackRef = NULL; /* * Clear the statistics for this driver */ InstancePtr->Stats.Interrupts = 0; /* Initialize the registers of each timer/counter in the device */ for (TmrCtrNumber = TmrCtrLowIndex; TmrCtrNumber < TmrCtrHighIndex; TmrCtrNumber++) { /* * Set the Compare register to 0 */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TLR_OFFSET, 0); /* * Reset the timer and the interrupt, the reset bit will need to * be cleared after this */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK); /* * Set the control/status register to complete initialization by * clearing the reset bit which was just set */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, 0); } /* * Indicate the instance is ready to use, successfully initialized */ InstancePtr->IsReady = XIL_COMPONENT_IS_READY; return XST_SUCCESS; }
/** * * Runs a self-test on the driver/device. This test verifies that the specified * timer counter of the device can be enabled and increments. * * @param InstancePtr is a pointer to the XTmrCtr instance. * @param TmrCtrNumber is the timer counter of the device to operate on. * Each device may contain multiple timer counters. The timer * number is a zero based number with a range of * 0 - (XTC_DEVICE_TIMER_COUNT - 1). * * @return * - XST_SUCCESS if self-test was successful * - XST_FAILURE if the timer is not incrementing. * * @note * * This is a destructive test using the provided timer. The current settings * of the timer are returned to the initialized values and all settings at the * time this function is called are overwritten. * ******************************************************************************/ int XTmrCtr_SelfTest(XTmrCtr * InstancePtr, u8 TmrCtrNumber) { u32 TimerCount1 = 0; u32 TimerCount2 = 0; u16 Count = 0; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Set the Capture register to 0 */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TLR_OFFSET, 0); /* * Reset the timer and the interrupt */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK); /* * Set the control/status register to enable timer */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, XTC_CSR_ENABLE_TMR_MASK); /* * Read the timer */ TimerCount1 = XTmrCtr_ReadReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCR_OFFSET); /* * Make sure timer is incrementing if the Count rolls over to zero * and the timer still has not incremented an error is returned */ do { TimerCount2 = XTmrCtr_ReadReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCR_OFFSET); Count++; } while ((TimerCount1 == TimerCount2) && (Count != 0)); /* * Reset the timer and the interrupt */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK); /* * Set the control/status register to 0 to complete initialization * this disables the timer completely and allows it to be used again */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, 0); if (TimerCount1 == TimerCount2) { return XST_FAILURE; } else { return XST_SUCCESS; } }
/** * * Initializes a specific timer/counter instance/driver. Initialize fields of * the XTmrCtr structure, then reset the timer/counter * * @param InstancePtr is a pointer to the XTmrCtr instance. * @param DeviceId is the unique id of the device controlled by this * XTmrCtr component. Passing in a device id associates the * generic XTmrCtr component to a specific device, as chosen by * the caller or application developer. * * @return * - XST_SUCCESS if initialization was successful * - XST_DEVICE_IS_STARTED if the device has already been started * - XST_DEVICE_NOT_FOUND if the device doesn't exist * * @note None. * ******************************************************************************/ int XTmrCtr_Initialize(XTmrCtr * InstancePtr, u16 DeviceId) { XTmrCtr_Config *TmrCtrConfigPtr; int TmrCtrNumber; u32 StatusReg; Xil_AssertNonvoid(InstancePtr != NULL); /* * Lookup the device configuration in the temporary CROM table. Use this * configuration info down below when initializing this component. */ TmrCtrConfigPtr = XTmrCtr_LookupConfig(DeviceId); if (TmrCtrConfigPtr == (XTmrCtr_Config *) NULL) { return XST_DEVICE_NOT_FOUND; } /* * Check each of the timer counters of the device, if any are already * running, then the device should not be initialized. This allows the * user to stop the device and reinitialize, but prevents a user from * inadvertently initializing. */ for (TmrCtrNumber = 0; TmrCtrNumber < XTC_DEVICE_TIMER_COUNT; TmrCtrNumber++) { /* * Read the current register contents and check if the timer * counter is started and running, note that the register read * is not using the base address in the instance so this is not * destructive if the timer counter is already started */ StatusReg = XTmrCtr_ReadReg(TmrCtrConfigPtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET); if (StatusReg & XTC_CSR_ENABLE_TMR_MASK) { return XST_DEVICE_IS_STARTED; } } /* * Set some default values, including setting the callback * handlers to stubs. */ InstancePtr->BaseAddress = TmrCtrConfigPtr->BaseAddress; InstancePtr->Handler = NULL; InstancePtr->CallBackRef = NULL; /* * Clear the statistics for this driver */ InstancePtr->Stats.Interrupts = 0; /* Initialize the registers of each timer/counter in the device */ for (TmrCtrNumber = 0; TmrCtrNumber < XTC_DEVICE_TIMER_COUNT; TmrCtrNumber++) { /* * Set the Compare register to 0 */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TLR_OFFSET, 0); /* * Reset the timer and the interrupt, the reset bit will need to * be cleared after this */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK); /* * Set the control/status register to complete initialization by * clearing the reset bit which was just set */ XTmrCtr_WriteReg(InstancePtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, 0); } /* * Indicate the instance is ready to use, successfully initialized */ InstancePtr->IsReady = XIL_COMPONENT_IS_READY; return XST_SUCCESS; }
/** * * Interrupt Service Routine (ISR) for the driver. This function only performs * processing for the device and does not save and restore the interrupt context. * * @param InstancePtr contains a pointer to the timer/counter instance for * the interrupt. * * @return None. * * @note None. * ******************************************************************************/ void XTmrCtr_InterruptHandler(void *InstancePtr) { XTmrCtr *TmrCtrPtr = NULL; u8 TmrCtrNumber; u32 ControlStatusReg; /* * Verify that each of the inputs are valid. */ Xil_AssertVoid(InstancePtr != NULL); /* * Convert the non-typed pointer to an timer/counter instance pointer * such that there is access to the timer/counter */ TmrCtrPtr = (XTmrCtr *) InstancePtr; /* * Loop thru each timer counter in the device and call the callback * function for each timer which has caused an interrupt */ for (TmrCtrNumber = 0; TmrCtrNumber < XTC_DEVICE_TIMER_COUNT; TmrCtrNumber++) { ControlStatusReg = XTmrCtr_ReadReg(TmrCtrPtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET); /* * Check if interrupt is enabled */ if (ControlStatusReg & XTC_CSR_ENABLE_INT_MASK) { /* * Check if timer expired and interrupt occured */ if (ControlStatusReg & XTC_CSR_INT_OCCURED_MASK) { /* * Increment statistics for the number of * interrupts and call the callback to handle * any application specific processing */ TmrCtrPtr->Stats.Interrupts++; TmrCtrPtr->Handler(TmrCtrPtr->CallBackRef, TmrCtrNumber); /* * Read the new Control/Status Register content. */ ControlStatusReg = XTmrCtr_ReadReg(TmrCtrPtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET); /* * If in compare mode and a single shot rather * than auto reload mode then disable the timer * and reset it such so that the interrupt can * be acknowledged, this should be only temporary * till the hardware is fixed */ if (((ControlStatusReg & XTC_CSR_AUTO_RELOAD_MASK) == 0) && ((ControlStatusReg & XTC_CSR_CAPTURE_MODE_MASK)== 0)) { /* * Disable the timer counter and * reset it such that the timer * counter is loaded with the * reset value allowing the * interrupt to be acknowledged */ ControlStatusReg &= ~XTC_CSR_ENABLE_TMR_MASK; XTmrCtr_WriteReg( TmrCtrPtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, ControlStatusReg | XTC_CSR_LOAD_MASK); /* * Clear the reset condition, * the reset bit must be * manually cleared by a 2nd write * to the register */ XTmrCtr_WriteReg( TmrCtrPtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, ControlStatusReg); } /* * Acknowledge the interrupt by clearing the * interrupt bit in the timer control status * register, this is done after calling the * handler so the application could call * IsExpired, the interrupt is cleared by * writing a 1 to the interrupt bit of the * register without changing any of the other * bits */ XTmrCtr_WriteReg(TmrCtrPtr->BaseAddress, TmrCtrNumber, XTC_TCSR_OFFSET, ControlStatusReg | XTC_CSR_INT_OCCURED_MASK); } } } }
int main(void) { u32 cmd; u32 count; u32 GenerateValue, CaptureDuration; u8 NumberOfTimes; u32 count1, count2; u32 status; u8 iop_pins[8]; u32 timer_pin; // Initialize Pmod pmod_init(0,1); /* * Configuring Pmod IO switch * Timer is connected to bit[0] of the Channel 1 of AXI GPIO instance * This configuration is changed later */ config_pmod_switch(TIMER, GPIO_1, GPIO_2, GPIO_3, GPIO_4, GPIO_5, GPIO_6, GPIO_7); // by default tristate timer output Xil_Out32(XPAR_GPIO_0_BASEADDR+0x08,1); while(1){ while(MAILBOX_CMD_ADDR==0); // wait for CMD to be issued cmd = MAILBOX_CMD_ADDR; switch(cmd){ case CONFIG_IOP_SWITCH: // read new pin configuration timer_pin = MAILBOX_DATA(0); iop_pins[0] = GPIO_0; iop_pins[1] = GPIO_1; iop_pins[2] = GPIO_2; iop_pins[3] = GPIO_3; iop_pins[4] = GPIO_4; iop_pins[5] = GPIO_5; iop_pins[6] = GPIO_6; iop_pins[7] = GPIO_7; // set new pin configuration iop_pins[timer_pin] = TIMER; config_pmod_switch(iop_pins[0], iop_pins[1], iop_pins[2], iop_pins[3], iop_pins[4], iop_pins[5], iop_pins[6], iop_pins[7]); Xil_Out32(XPAR_GPIO_0_BASEADDR+0x08,1); MAILBOX_CMD_ADDR = 0x0; break; case STOP_TIMER: XTmrCtr_Stop(&TimerInst_0, 0); XTmrCtr_Stop(&TimerInst_0, 1); MAILBOX_CMD_ADDR = 0x0; break; case GENERATE_FOREVER: // tri-state control negated so output can be driven Xil_Out32(XPAR_GPIO_0_BASEADDR+0x08,0); // get period value in multiple of 10 ns clock period GenerateValue=MAILBOX_DATA(0); XTmrCtr_SetResetValue(&TimerInst_0, 0, GenerateValue); XTmrCtr_SetOptions(&TimerInst_0, 0, XTC_AUTO_RELOAD_OPTION | XTC_CSR_LOAD_MASK | XTC_CSR_EXT_GENERATE_MASK | XTC_CSR_DOWN_COUNT_MASK); XTmrCtr_Start(&TimerInst_0, 0); MAILBOX_CMD_ADDR = 0x0; break; case GENERATE_N_TIMES: // tri-state control negated so output can be driven Xil_Out32(XPAR_GPIO_0_BASEADDR+0x08,0); // bits 7:0 number of times, rest is period GenerateValue=MAILBOX_DATA(0)>>8; NumberOfTimes=MAILBOX_DATA(0) & 0xff; XTmrCtr_SetResetValue(&TimerInst_0, 0, GenerateValue); XTmrCtr_SetOptions(&TimerInst_0, 0, XTC_AUTO_RELOAD_OPTION | XTC_CSR_LOAD_MASK | XTC_CSR_EXT_GENERATE_MASK | XTC_CSR_DOWN_COUNT_MASK); XTmrCtr_Start(&TimerInst_0, 0); while(NumberOfTimes){ // wait for NumberOfTimes to count down to 0 status=XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0); if(status & 0x100){ // wait for the asserted edge, reset the flag XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, status); NumberOfTimes--; } } XTmrCtr_Stop(&TimerInst_0, 0); MAILBOX_CMD_ADDR = 0x0; break; case EVENT_OCCURED: // tri-state control asserted to enable input to capture Xil_Out32(XPAR_GPIO_0_BASEADDR+0x08,1); // get period value in multiple of 10 ns clock period CaptureDuration=MAILBOX_DATA(0); /* * Use timer module 0 for event counts * Use timer module 1 for the duration * Load timer 1's Load register */ XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 1, TLR0, CaptureDuration); /* * 0001 0010 0010 => no cascade, no all timers, * no pwm, clear interrupt status, * disable timer, no interrupt, * load timer, hold capture value, * disable external capture, * disable external generate, * down counter, generate mode */ // clear int flag and load counter XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 1, TCSR0, 0x122); // enable timer 1 in compare mode, no load counter XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 1, TCSR0, 0x082); /* * 0001 1000 1001 => no cascade, no all timers, * no pwm, clear interrupt status, * enable timer, no interrupt, * no load timer, hold capture value, * enable external capture, * disable external generate, * up counter, capture mode */ XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, 0x189); while(1) { if((XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 1, TCSR0) & 0x100)){ // if duration over then get out, disable counter 1 XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 1, TCSR0, 0x100); MAILBOX_DATA(0)=0; break; } if((XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0) & 0x100)){ // wait for the asserted edge, disable counter 0 XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, 0x100); MAILBOX_DATA(0)=1; break; } } MAILBOX_CMD_ADDR = 0x0; break; case COUNT_EVENTS: // tri-state control asserted to enable input to capture Xil_Out32(XPAR_GPIO_0_BASEADDR+0x08,1); // get period value in multiple of 10 ns clock period CaptureDuration=MAILBOX_DATA(0); count=0; /* * Use timer module 0 for event counts * Use timer module 1 for the duration * Load timer 1's Load register */ XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 1, TLR0, CaptureDuration); /* * 0001 0010 0010 => no cascade, no all timers, no pwm, * clear interrupt status, disable timer, * no interrupt, load timer, * hold capture value, * disable external capture, * disable external generate, * down counter, generate mode */ // clear int flag and load counter XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 1, TCSR0, 0x122); // enable timer 1 in compare mode, no load counter XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 1, TCSR0, 0x082); /* 0001 1000 1001 => no cascade, no all timers, no pwm, * clear interrupt status, enable timer, * no interrupt, no load timer, * hold capture value, * enable external capture, * disable external generate, up counter, * capture mode */ XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, 0x189); while(1) { if((XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 1, TCSR0) & 0x100)){ // if duration over then get out, disable counter 1 XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 1, TCSR0, 0x100); break; } if((XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0) & 0x100)){ // wait for the asserted edge XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, 0x189); count++; } } MAILBOX_DATA(0)=count; MAILBOX_CMD_ADDR = 0x0; break; case MEASURE_PERIOD: // tri-state control asserted to enable input to capture Xil_Out32(XPAR_GPIO_0_BASEADDR+0x08,1); /* * Use timer module 0 for event capture * Use module 1 for the maximum duration */ count1=0; count2=0; /* * 0001 1000 1001 => no cascade, no all timers, no pwm, * clear interrupt status, enable timer, * no interrupt, no load timer, * hold capture value, * enable external capture, * disable external generate, * up counter, capture mode */ // clear capture flag and enable capture mode XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, 0x189); // skip high or 1st asserted edge while(!(XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0) & 0x100)); // dummy read XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TLR0); // clear capture flag and enable capture mode XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, 0x189); // wait for 1st asserted edge while(!(XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0) & 0x100)); // read counter value count1=XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TLR0); // reset interrupt flag XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, 0x189); // wait for 2nd asserted edge while(!(XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0) & 0x100)); // read counter value count2=XTmrCtr_ReadReg(XPAR_TMRCTR_0_BASEADDR, 0, TLR0); // clear capture flag and disable XTmrCtr_WriteReg(XPAR_TMRCTR_0_BASEADDR, 0, TCSR0, 0x100); MAILBOX_DATA(0)=count2-count1; MAILBOX_CMD_ADDR = 0x0; break; default: MAILBOX_CMD_ADDR = 0x0; break; } } return 0; }