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: 
Visitor coxbrianm
Visitor
9,555 Views
Registered: ‎12-23-2011

Microblaze MCS External Interrupt Setup

I've been trying to setup and use the external interrupt port on a Microblaze MCS design.

No matter what I try, I can't get the interrupt service routine (void myIntHandler in the code below) to run.

 

The ISR has a couple of simple writes that I wanted to use to confirm that the ISR runs.

I have verified that the write commands work fine if I execute them in main instead of the ISR.  When they are inside the ISR they never execute.

 

Note in main the 3 XIOModule function calls.  I verified with the debugger that these ALL return XST_SUCCESS.

 

The interupt is configured as a high, level interrupt.  I also tried edge triggered without success.

Here is a picture of the setup screen:

 

Untitled.png

 

I just connected the interrupt pin to a slow square wave signal in ISE (much slower then the MCS clock).

 

I'm using a Spartan 6, SDK 13.4 and ISE 13.4.

I also attached my xparameters.h file.

Not sure what other info anyone might need to help with this problem.

 

Thanks!

 

C code:

 

#include "xbasic_types.h"

#include "xio.h"

#include "mb_interface.h"

#include "xparameters.h"

#include "xiomodule.h"

#include "xil_exception.h"

 

//global variables

 

XIOModule IOModule;

 

void myIntHandler(void * arg)

{

//couple of dummy writes

 

XIo_Out32(0xC000020C, 0x123);

XIo_Out32(0xC000030C, 0x456);

 

XIOModule_Acknowledge(&IOModule, XPAR_IOMODULE_0_SYSTEM_INTC_INTERRUPT_0_INTR);

}

 

 

int main()

 

{

 

XStatus Status;

 

Status = XIOModule_Initialize(&IOModule, XPAR_IOMODULE_0_DEVICE_ID);

 

Status = XIOModule_Start(&IOModule);

 

Status = XIOModule_Connect(&IOModule, XPAR_IOMODULE_0_SYSTEM_INTC_INTERRUPT_0_INTR,

(XInterruptHandler)myIntHandler, (void*) 0);

 

XIOModule_Enable(&IOModule, XPAR_IOMODULE_0_SYSTEM_INTC_INTERRUPT_0_INTR);

 

 

for(;;)

{

//wait for an interrupt

}

return 0;

 

}

 

0 Kudos
5 Replies
Visitor coxbrianm
Visitor
9,532 Views
Registered: ‎12-23-2011

Re: Microblaze MCS External Interrupt Setup

I realize I neglected to include microblaze_enable_interrupts();

I added this immiedietly after XIOModule_Enable, but this did NOT produce any change.  The ISR still does not run.

Can anyone offer me a suggestion?

Thanks!

0 Kudos
Xilinx Employee
Xilinx Employee
9,484 Views
Registered: ‎08-06-2007

Re: Microblaze MCS External Interrupt Setup

Hi,

 

Why do you configure the interrupt to be level (high) when the signal is a square signal?

When the interrupt handler checks which interrupt that is active, the square signal might be in low state and thus no interrupts source is active.

Please configure it to be edge or change the interrupt source.

 

Göran

0 Kudos
Visitor coxbrianm
Visitor
9,438 Views
Registered: ‎12-23-2011

Re: Microblaze MCS External Interrupt Setup

Thanks for your reply.

 

I originally had edge sensitive interrupts but since the ISR wasn't firing, I tried changing to level sensitive (among other things). 

 

I have now managed to get the ISR to fire by making a couple of changes to the C code.

First, I changed references to XPAR_IOMODULE_0_SYSTEM_INTC_INTERRUPT_0_INTR to be

XIN_IOMODULE_EXTERNAL_INTERRUPT_INTR instead.

Second, I added the line

microblaze_register_handler(XIOModule_DeviceInterruptHandler, XPAR_IOMODULE_0_DEVICE_ID );

This is also with the interrupts set back to edge sensitive.  Changes in RED

 

Below is my current code:

 

#include "xbasic_types.h" //for Xint data types

#include "xio.h" //for IO bus read/writes using XIo_Out and XIo_In functions

#include "xiomodule.h" //for interrupt handling and GPIO read/write functions

#include "mb_interface.h" //more interrupt stuff

 

//global variables

 

XIOModule IOModule;

 

Xint32 dummy1, dummy2, dummy3, dummy4;

 

void myIntHandler(void *CallBackRef)

{

XIOModule_Acknowledge(&IOModule, XIN_IOMODULE_EXTERNAL_INTERRUPT_INTR);

 

dummy1 = -1*(XIo_In32(0xC0000200) - 2048);

dummy2 = -1*(XIo_In32(0xC0000204) - 2048);

dummy3 = -1*(XIo_In32(0xC0000210) - 2048);

 

dummy4 = dummy3*(dummy1 - dummy2);

 

if (dummy4 > 2047)

dummy4 = 2047;

else if (dummy4 < -2047)

dummy4 = -2047;

 

//write back to vhdl section

 

XIo_Out32(0xC0000230, dummy4);

}

 

 

int main()

{

//external interrupt setup

 

XIOModule_Initialize(&IOModule, XPAR_IOMODULE_0_DEVICE_ID);

 

microblaze_register_handler(XIOModule_DeviceInterruptHandler, XPAR_IOMODULE_0_DEVICE_ID );

 

XIOModule_Start(&IOModule);

 

XIOModule_Connect(&IOModule, XIN_IOMODULE_EXTERNAL_INTERRUPT_INTR, myIntHandler, (void*) 0);

 

XIOModule_Enable(&IOModule, XIN_IOMODULE_EXTERNAL_INTERRUPT_INTR);

 

microblaze_enable_interrupts();

 

for(;;)

{

//wait for an interrupt

 

}

return 0;

}

 

 

However, this is not the end of the story.  There is now something else happening I don't understand that I would appreciate some further help with.

 

There appears to be a very long delay between when the interrupt acknowledge signal (INTC_IRQ) goes high and when the code within the ISR actually starts to run.

Check out the picture below from chipscope pro.

 

chipscope2.png

 

The clk signal in the picture is running at 200 KHz.  The INTC_Interrupt(0) signal is being driven by VHDL logic.  It is set up to trigger an interrupt at the positive edge of this clock.  The MCS is clocked with a separate 128 MHz signal.

 

Check out the behavior of the acknowledge signal, INTC_IRQ.  After the first interrupt it stays high for a very long period of time and during this time none of the read/write instructions in the ISR execute.  Why would that be?  When it finally clears the 3 read instructions execute as signified by the 3 read strobes.  But then the write instruction doesn't execute before another interrupt comes in.

 

After the second interrupt, the acknowledge signal for some reason falls after a much shorter period of time and the ISR appears to return to the point it had previously left off, but now the write instruction executes whily the acknowledge signal is still high?

 

What might be going on?  Does this have something to do with my use of the XIOModule_Acknowledge function?

 

Here is the code generating the interrupt signal:

 

ProcMicroInterruptRise: process(reset, adc_clk_in, INTC_IRQ)
 begin
  if reset = '1' then
   INTC_Interrupt <= "0";
   inttest4 <= '0';
  elsif adc_clk_in'event and adc_clk_in = '1' then
   if EnableCh2 = '1' then
    INTC_Interrupt <= "1"; 
    inttest4 <= not inttest4;
   end if;
  end if;
   
  if INTC_IRQ = '1' then
   INTC_Interrupt <= "0";
  end if;
   
 end process;

 

Thanks!

0 Kudos
Xilinx Employee
Xilinx Employee
9,429 Views
Registered: ‎08-06-2007

Re: Microblaze MCS External Interrupt Setup

Hi,

 

The jitter you experience in the interrupt response time can have multiple causes.

1. What is MicroBlaze executing when the interrupt occurs?

2. Are you using fast interrupt or normal interrupts? Fast Interrupt handling is 10x quicker to response (in average)

3. What is happening in the rest of the system when MIcroBlaze is interrupted?

 

After MicroBlaze sees the INTC_IRQ, it will first see if interrupts are enabled (some code temporarily turns off interrupts of critical sections).

It will then jump to 0x10 (with fast interrupts it will jump to the interrupt handler directly) after completing all the current instructions in the pipeline. WIth normal interrupts, it will jump from 0x10 to the generic interrupt handler that will check the interrupt handler to see what interrupt are active and jump to the handler for each interrupt in turn.

With fast interrupt, MicroBlaze will skip the generic interrupt handler and jump directly to the handler for the specific interrupt.

For more information read about "Low latency interrupt mode" in the MicroBlaze reference guide (ug084, page 171).

 

Göran

0 Kudos
Visitor coxbrianm
Visitor
9,385 Views
Registered: ‎12-23-2011

Re: Microblaze MCS External Interrupt Setup

1. Microblaze should not be executing anything when the interrupt occurs. It should just be sitting inside the for loop in main waiting for an interrupt to occur.

2. How do I identify what type of interrupt I am using? I looked through xiomodule.h which I thought included all of the function prototypes for interrupt handling and I don't see anythign specifically related to normal or fast interrupts. Can you review the code I use to configure interrupt handling and tell me what would need to change in order to use fast interrupts?

int main()
{
//external interrupt setup

XIOModule_Initialize(&IOModule, XPAR_IOMODULE_0_DEVICE_ID);

microblaze_register_handler(XIOModule_DeviceInterruptHandler, XPAR_IOMODULE_0_DEVICE_ID );

XIOModule_Start(&IOModule);

XIOModule_Connect(&IOModule, XIN_IOMODULE_EXTERNAL_INTERRUPT_INTR, myIntHandler, (void*) 0);

XIOModule_Enable(&IOModule, XIN_IOMODULE_EXTERNAL_INTERRUPT_INTR);

microblaze_enable_interrupts();

3. Nothing much else should be happening with the rest of the system. In the vhdl logic there is some code to read from an ADC but this isn't related to microblaze. There is also the code to trigger interrupts which I included earlier. The FPGA is only 34% full.

Thanks!
0 Kudos