UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Explorer
Explorer
7,407 Views
Registered: ‎05-25-2016

Time counter won't interrupt from load register

Hello,

 

I'm new to uBlaze and have a noob question.  I'm just trying to get a simple timer to blink LEDs based on a timer interrupt.  The interrupt seems to work, but not based on the reset value I load into the load register.  It looks like it just interrupts when the register rolls over completely from all F's to 0's.  I believe this because I get the interrupt after 30 or 40 seconds which seems to make sense for a 32 bit register rolling over at 100Mhz.  Is there anything obvious I'm doing wrong?  Below is my code.

 

    /*********************************************************************************
    * Configure UART for debug
    *********************************************************************************/
    // Init uart
    XUartLite_Initialize(&debug_uart, XPAR_AXI_UARTLITE_0_DEVICE_ID);
    // Clear FIFOs
    XUartLite_ResetFifos(&debug_uart);
    // Self test
    if(XUartLite_SelfTest(&debug_uart) == XST_SUCCESS){
    	xil_printf("UART Configured!\n\r");
    }
    // Enable Interrupts
    //XUartLite_EnableInterrupt(&debug_uart);
    // Assigne rx and tx handlers
    //XUartLite_SetRecvHandler(&debug_uart, (XUartLite_Handler)debug_uart_rx_isr, (void*)0);
    //XUartLite_SetSendHandler(&debug_uart, (XUartLite_Handler)debug_uart_tx_isr, (void*)0);

    Status = XTmrCtr_Initialize(&Timer0, XPAR_TMRCTR_0_DEVICE_ID);
    if(Status != XST_SUCCESS){
        	while(1);
    }

    /*********************************************************************************
    * Configure interrupt controller
    *********************************************************************************/
    Status = XIntc_Initialize(&Interrupt_Controller, XPAR_MICROBLAZE_0_AXI_INTC_DEVICE_ID);
    if(Status != XST_SUCCESS){
        	while(1);
    }

    // Connect Timer interrupt to handler
    Status = XIntc_Connect(&Interrupt_Controller, XPAR_MICROBLAZE_0_AXI_INTC_AXI_TIMER_0_INTERRUPT_INTR, (XInterruptHandler)XTmrCtr_InterruptHandler, (void*)&Timer0);
    if(Status != XST_SUCCESS){
     	while(1);
    }

    // Enable Timer0 Interrupts
    XIntc_Enable(&Interrupt_Controller, XPAR_MICROBLAZE_0_AXI_INTC_AXI_TIMER_0_INTERRUPT_INTR);
    // Check for error
    //Status = XIntc_SelfTest(&Interrupt_Controller);
    //if(Status != XST_SUCCESS){
    // 	while(1);
    //}
    // Start controller
    XIntc_Start(&Interrupt_Controller, XIN_REAL_MODE);




    /***********************************************************************


********** * Configure Timer *********************************************************************************/ XTmrCtr_SetHandler(&Timer0, (XTmrCtr_Handler)MyTimerIsr, &Timer0); XTmrCtr_SetOptions(&Timer0, XPAR_TMRCTR_0_DEVICE_ID, XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION); XTmrCtr_SetResetValue(&Timer0, XPAR_TMRCTR_0_DEVICE_ID, 0x3FFFFF); XTmrCtr_Reset(&Timer0, XPAR_TMRCTR_0_DEVICE_ID); XTmrCtr_Stop(&Timer0, XPAR_TMRCTR_0_DEVICE_ID); /********************************************************************************* * Configure LED GPIO *********************************************************************************/ XGpio_Initialize(&LEDs, XPAR_LED_DEVICE_ID); XGpio_SetDataDirection(&LEDs, 1, 0x00); microblaze_enable_interrupts(); XTmrCtr_Start(&Timer0, XPAR_TMRCTR_0_DEVICE_ID);

 

 

I also noticed that when I have this block enabled:

 

    // Check for error
    Status = XIntc_SelfTest(&Interrupt_Controller);
    if(Status != XST_SUCCESS){
     	while(1);
    }
    

I get a 1201 error returned that indicates that XIntc_SelfTest failed at this point below:

 

 

 

 

	/*
	 * Verify that there are no interrupts by reading the interrupt status
	 */
	CurrentISR = XIntc_In32(InstancePtr->BaseAddress + XIN_ISR_OFFSET);

	/*
	 * ISR should be zero after all interrupts are acknowledged
	 */
	if (CurrentISR != 0) {
		return XST_INTC_FAIL_SELFTEST;
	}

 

 

Does anyone have any ideas?  I've been stuck on this simple problem of getting a basic timer to work for far too long. 

0 Kudos
4 Replies
Explorer
Explorer
7,349 Views
Registered: ‎05-25-2016

Re: Time counter won't interrupt from load register

So I finally figured this out.  I am just posting up my solution for the community.  I configured my timer/interrupt controller as shown below.

 

    /*********************************************************************************
    * Configure interrupt controller
    *********************************************************************************/
    Status = XIntc_Initialize(&Interrupt_Controller, XPAR_MICROBLAZE_0_AXI_INTC_DEVICE_ID);
    if(Status != XST_SUCCESS){
        	while(1);
    }
    // Connect Timer interrupt to handler
    Status = XIntc_Connect(&Interrupt_Controller, XPAR_MICROBLAZE_0_AXI_INTC_AXI_TIMER_0_INTERRUPT_INTR, (XInterruptHandler)XTmrCtr_InterruptHandler, (void*)&Timer0);
    if(Status != XST_SUCCESS){
    	xil_printf("Fail!");
    }
    Status = XIntc_Connect(&Interrupt_Controller, XPAR_MICROBLAZE_0_AXI_INTC_AXI_UARTLITE_0_INTERRUPT_INTR, (XInterruptHandler)XUartLite_InterruptHandler, (void*)&debug_uart);
    if(Status != XST_SUCCESS){
    	xil_printf("Fail!");
    }
    // Enable Timer0 Interrupts
    XIntc_Enable(&Interrupt_Controller, XPAR_MICROBLAZE_0_AXI_INTC_AXI_TIMER_0_INTERRUPT_INTR);
    // Enable XUartLite Interrupts
    XIntc_Enable(&Interrupt_Controller, XPAR_MICROBLAZE_0_AXI_INTC_AXI_UARTLITE_0_INTERRUPT_INTR);

    // Check for error
    Status = XIntc_SelfTest(&Interrupt_Controller);
    if(Status != XST_SUCCESS){
     	xil_printf("Fail!");
    }
    // Start controller
    XIntc_Start(&Interrupt_Controller, XIN_REAL_MODE);

 

The configuration of the timer looks like this:

    // Init timer
    Status = XTmrCtr_Initialize(&Timer0, XPAR_TMRCTR_0_DEVICE_ID);
    if(Status != XST_SUCCESS){
    	xil_printf("Fail!");
    }
    XTmrCtr_SetHandler(&Timer0, (XTmrCtr_Handler)MyTimerIsr, &Timer0);
    XTmrCtr_SetOptions(&Timer0, XPAR_TMRCTR_0_DEVICE_ID,	XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_DOWN_COUNT_OPTION);
    XTmrCtr_SetResetValue(&Timer0, XPAR_TMRCTR_0_DEVICE_ID, 0xFFFFFF);
    XTmrCtr_Reset(&Timer0, XPAR_TMRCTR_0_DEVICE_ID);
    XTmrCtr_Stop(&Timer0, XPAR_TMRCTR_0_DEVICE_ID);

 

It looks like one big problem for me was that I was setting the load register to a number that I wanted the timer to stop at, but in up mode it doesn't seem to ever stop.  When I changed the timer to count in "down" mode it started working.  Who knew you couldn't use either.  I still don't know why my interrupt controller self check was failing, but it seems to be passing now that the timer is working. 

 

I also added code to reset the timer by writing a 1 to the interrupt flag bit in the timer control register.  I guess you don't have to explicitly do this, but I keep it in just in case.  Below is the ISR:

void MyTimerIsr(void *CallBackRef, u8 TmrCtrNumber)
{
	XTmrCtr *InstancePtr = (XTmrCtr *)CallBackRef;
	uint32_t ControlStatusReg;


	LED_cnt++;


	//XGpio_DiscreteWrite(&LEDs, 1, (0xFF ^ XGpio_DiscreteRead(&LEDs, 1)));
	XGpio_DiscreteWrite(&LEDs, 1, LED_cnt);

	// Reset ISR Bit
	ControlStatusReg = XTmrCtr_ReadReg(InstancePtr->BaseAddress, 0, XTC_TCSR_OFFSET);
	XTmrCtr_WriteReg(InstancePtr->BaseAddress, 0, XTC_TCSR_OFFSET, ControlStatusReg | XTC_CSR_INT_OCCURED_MASK);

}
0 Kudos
Explorer
Explorer
7,200 Views
Registered: ‎05-25-2016

Re: Time counter won't interrupt from load register

So I figured this out and wanted to reply with my solution.  When setting a count value as I was trying to do I had to set the counter to COUNTDOWN mode instead of count up mode.  After that things started working. 

0 Kudos
Highlighted
Contributor
Contributor
1,168 Views
Registered: ‎08-28-2017

Re: Time counter won't interrupt from load register

Hi @m3atwad

 

How to calculate the TIMER_LOAD_VALUE for specific time (like 1ms)?.

 

By private timer can i generate 1ms?

 

please suggest me regarding this .

 

Thanks and Best Regards

Vinod Sajjan 

0 Kudos
Explorer
Explorer
1,165 Views
Registered: ‎05-25-2016

Re: Time counter won't interrupt from load register

Your count value is just clock 1ms/clock period.  Just write this into your TIMER_LOAD_VALUE and set the timer to count down mode.  Your clock rate will be your axi clock if you are using the axi timer peripheral.