cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Participant
Participant
21,112 Views
Registered: ‎11-27-2007

MicroBlaze Timer Interrupt

Jump to solution

I've created a simple MicroBlaze system and am trying to trigger an interrupt, but obviously it's not working. I've basically adapted the xtmrctr_intr_example.c example application. I'm not familiar with Microblaze or C at all, so it's possible I'm doing something very stupid. 

 

I started from the simple hello_world.c and started adding in what looked necessary from xtmrctr_intr_example.c:

 

#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "xtmrctr.h"
#include "xintc.h"

#define TMRCTR_DEVICE_ID XPAR_AXI_TIMER_0_DEVICE_ID
#define TMRCTR TMRCTR_DEVICE_ID
#define TMRCTR_INTERRUPT_ID XPAR_MICROBLAZE_0_INTC_AXI_TIMER_0_INTERRUPT_INTR

#define TIMER_DEVICE_ID XPAR_AXI_TIMER_1_DEVICE_ID
#define TIMER TIMER_DEVICE_ID

#define TIMER_FREQ XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ
//#define ONE_SECOND TIMER_FREQ
#define ONE_SECOND 500000000

#define INTC_DEVICE_ID XPAR_MICROBLAZE_0_INTC_DEVICE_ID

volatile int timerExpired;

XTmrCtr* gpTmrCtr;	// Pointer to Timer Counter, used for general timing
XTmrCtr* gpTimer;	// Pointer to 64-bit Timer, used for absolute time
XIntc* gpIntc;		// Pointer to Interrupt Controller
u8 gcTimerInterrupts = 0;	// Number of times TmrCtr interrupts

void TimerCounterHandler(void* CallBackRef, u8 TmrCtrNumber);

int main()
{

	init_platform();

	XIntc intc;
	gpIntc = &intc;

	XTmrCtr tmrctr;
	gpTmrCtr = &tmrctr;

	XTmrCtrStats stats;

	int status = XST_FAILURE;
	u32 options = 0;

	// Initialize the first counter
	status = XTmrCtr_Initialize( gpTmrCtr, 0 );
	if ( status != XST_SUCCESS ) return XST_FAILURE;
	xil_printf("Initialized TmrCtr\n\r");

	// Initialize the interrupt controller
	status = XIntc_Initialize( gpIntc, INTC_DEVICE_ID );
	if ( status != XST_SUCCESS ) return XST_FAILURE;
	xil_printf("Initialized XIntc\n\r");

	// Connect a device driver handler to call when an interrupt triggers for a device
	status = XIntc_Connect( gpIntc, TMRCTR_INTERRUPT_ID,
			(XInterruptHandler)XTmrCtr_InterruptHandler,
			(void*)gpTmrCtr );
	if ( status != XST_SUCCESS ) return XST_FAILURE;
	xil_printf("Connected interrupt handler for TMRCTR_INTERRUPT_ID\n\r");

	// Start the interrupt controller
	status = XIntc_Start( gpIntc, XIN_REAL_MODE );
	if ( status != XST_SUCCESS ) return XST_FAILURE;
	xil_printf("Started interrupts for XIntc in XIN_REAL_MODE\n\r");

	// Enable interrupt for the timer counter
	XIntc_Enable( gpIntc, TMRCTR_INTERRUPT_ID );
	xil_printf("Enabled interrupt for TMRCTR_INTERRUPT_ID\n\r");

	/*
	 * Setup the handler for the timer counter that will be called from the
	 * interrupt context when the timer expires, specify a pointer to the
	 * timer counter driver instance as the callback reference so the handler
	 * is able to access the instance data
	 */
	 XTmrCtr_SetHandler( gpTmrCtr, TimerCounterHandler, gpTmrCtr );
	 xil_printf("Set handler for XTmrCtr to TimerCounterHandler\n\r");

	 // Set the option to count down, enable the interrupt
	 XTmrCtr_SetOptions( gpTmrCtr, 0,
			XTC_DOWN_COUNT_OPTION | XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION );
	 xil_printf("Set TmrCtr options\n\r");

	 XTmrCtr_SetResetValue( gpTmrCtr, 0, ONE_SECOND );
	 xil_printf("Set reset value for XTmrCtr\n\r");

	 // Start the timer
	 XTmrCtr_Start( gpTmrCtr, 0 );
	 xil_printf("Started XTmrCtr\n\r");

	 options = XTmrCtr_GetOptions( gpTmrCtr, 0 );
	 xil_printf( "TCSR of TmrCtr(0): %08X\n\r", options );


	 xil_printf("Entering while loop in main()\n\r");
	 u32 cTmrCtr, i = 0;
	 while ( gcTimerInterrupts < 10 ) {
		 if ( i++ % 5000 == 0 ) {
			 cTmrCtr = XTmrCtr_GetValue( gpTmrCtr, 0 );
			 xil_printf("Current value of cTmrCtr = %d\n\r", cTmrCtr);
			 XTmrCtr_GetStats( gpTmrCtr, &stats );
			 xil_printf( "Current value of stats.Interrupts: %d\n\r", stats.Interrupts );
			 options = XTmrCtr_GetOptions( gpTmrCtr, 0 );
			 xil_printf( "TCSR of TmrCtr(0): %08X\n\r", options );
		 }

	 }

	 return status;

}

void TimerCounterHandler(void* CallBackRef, u8 TmrCtrNumber)
{
	xil_printf("TimerCounterHandler called\n\r");
	XTmrCtr* InstancePtr = (XTmrCtr*)CallBackRef;
	if (XTmrCtr_IsExpired(InstancePtr, TmrCtrNumber)) {
		gcTimerInterrupts++;
		xil_printf("gcTimerInterrupts = %d\n\r",gcTimerInterrupts);
		if(gcTimerInterrupts == 10) {
			XTmrCtr_SetOptions(InstancePtr, TmrCtrNumber, 0);
		}
	}
}

 I get this output:

Initialized TmrCtr
Initialized XIntc
Connected interrupt handler for TMRCTR_INTERRUPT_ID
Started interrupts for XIntc in XIN_REAL_MODE
Enabled interrupt for TMRCTR_INTERRUPT_ID
Set handler for XTmrCtr to TimerCounterHandler
Set TmrCtr options
Set reset value for XTmrCtr
Started XTmrCtr
TCSR of TmrCtr(0): 0000002C
Entering while loop in main()
Current value of cTmrCtr = 434891587
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 355536654
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 272026823
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 196552834
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 105602815
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 22360175
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 468499526
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 401487391
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 347911633
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 285599238
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 171185335
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C
Current value of cTmrCtr = 87587830
Current value of stats.Interrupts: 0
TCSR of TmrCtr(0): 0000002C

 So, it looks like the TCSR for TmrCtr(0) is correct, but it's obviously not ever triggering an interrupt. I don't know why.

 

What am I doing wrong for the interrupt?

 

Also, is there any particular reason this is so slow? This is running at 80MHz, and according to the system ticks the time to do 5k additions is between 1 and 2 seconds. Anyway, just going by system ticks, that's ~25k cycles for what should be a few instructions, which doesn't seem great...

 

 

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Anonymous
Not applicable
28,875 Views

I have attached an timer interrupt (old) tutorial to this thread

View solution in original post

4 Replies
Highlighted
Anonymous
Not applicable
28,876 Views

I have attached an timer interrupt (old) tutorial to this thread

View solution in original post

Highlighted
Participant
Participant
21,090 Views
Registered: ‎11-27-2007

Wow, so, all I had to do was add

 

#include "mb_interface.h"
microblaze_enable_interrupts();

in the appropriate places, and tada, it works. Thanks.

 

No idea why those lines aren't in the example applications.

 

0 Kudos
Highlighted
20,965 Views
Registered: ‎09-12-2013

Actually, the following is in the bottom of the example and achieves much the same result

 

 /*
  * initialize the exception table.
  */
 xil_exceptioninit();

 /*
  * register the interrupt controller handler with the exception table.
  */
 xil_exceptionregisterhandler(xil_exception_id_int,
     (xil_exceptionhandler)
     intc_handler,
     intcinstanceptr);

 /*
  * enable non-critical exceptions.
  */
 xil_exceptionenable();

 

This is what hooks the interrupt line on the microblaze to the interrupt handler and turns it on.  I think you'll find the exceptioninit is empty.  The reset is putting a pointer in the right microblaze vector table location to the intc handler, and turning the whole mess on.  Jeez... I almost sound knowledgeable.  I've been struggling with much the same for the last month or so.

0 Kudos
Highlighted
Visitor
Visitor
1,058 Views
Registered: ‎05-05-2020

Excuse me, i have the same problem with the timer interrupt demo, and i have enable microblaze interrupt, but it still didn't work normal,so i want downlod the attachment(Timer_interrupt.dpdf) for checking myself coding, but i can't download it , can you help send one to me ? thanks very much,e-mail:simon_xfl@126.com.

 

0 Kudos