3

I have a simple microblaze setup with two Gpio (Push button and switches). I want to handle both devices interrupts.

Here follows my current non-working code.

#include<xparameters.h>
#include<xgpio.h>
#include<xintc.h>
#include<xil_exception.h>

static XGpio PushBt;
static XGpio sw;
static XIntc myIntc;
int delay, limit=3000000;

void pb_int_handler(void *baseaddr_p) {
        Xuint32 dsr;

        //DSR contains the INFORMATION of which button was depressed, so we can switch
        //on its value.
        dsr = XGpio_DiscreteRead(&PushBt, 1);
        switch(dsr) {

            case 0x01:
                xil_printf("Up\r\n");
                for(delay=0;delay<limit;delay++){}; // delay cycle
                break;

            case 0x02:
                xil_printf("Left\r\n");
                for(delay=0;delay<limit;delay++){}; // delay cycle
                break;

            case 0x08:
                xil_printf("Right\r\n");
                for(delay=0;delay<limit;delay++){}; // delay cycle
                break;

            case 0x04:
                xil_printf("Down\r\n");
                for(delay=0;delay<limit;delay++){}; // delay cycle
                break;

            default : {}

        }
        //Clear the interrupt both in the Gpio instance as well as the interrupt controller
        XGpio_InterruptClear(&PushBt, 0x3);
        XIntc_Acknowledge(&myIntc,XPAR_AXI_INTC_0_PUSH_IP2INTC_IRPT_INTR);
    }

void sw_int_handler(void *baseaddr_p) {
        Xuint32 dsr;

        //DSR contains the INFORMATION of which button was depressed, so we can switch
        //on its value.
        dsr = XGpio_DiscreteRead(&sw, 1);
        switch(dsr) {

            case 0x00:
                xil_printf("Switches 00 \r\n");
                for(delay=0;delay<limit;delay++){}; // delay cycle
                break;

            case 0x01:
                xil_printf("Switches 01 \r\n");
                for(delay=0;delay<limit;delay++){}; // delay cycle
                break;

            case 0x02:
                xil_printf("Switches 02 \r\n");
                for(delay=0;delay<limit;delay++){}; // delay cycle
                break;

            case 0x03:
                xil_printf("Switches 03 \r\n");
                for(delay=0;delay<limit;delay++){}; // delay cycle
                break;

            default : {}

        }
        //Clear the interrupt both in the Gpio instance as well as the interrupt controller
        XGpio_InterruptClear(&sw, 0x3);
        XIntc_Acknowledge(&myIntc,XPAR_AXI_INTC_0_SW_IP2INTC_IRPT_INTR);
    }

int main(void) {

    xil_printf("Setting up peripherals...\r\n");
    for(delay=0;delay<limit;delay++){}; // delay cycle

    xil_printf("Setting up push buttons...\r\n");
    for(delay=0;delay<limit;delay++){}; // delay cycle

        XGpio_Initialize(&PushBt, XPAR_PUSH_DEVICE_ID);
        XGpio_SetDataDirection(&PushBt,1,1); //set pb as input port
        XGpio_InterruptEnable(&PushBt, XPAR_PUSH_IP2INTC_IRPT_MASK);
        XGpio_InterruptGlobalEnable(&PushBt);

    xil_printf("Setting up switches...\r\n");
    for(delay=0;delay<limit;delay++){}; // delay cycle

        XGpio_Initialize(&sw, XPAR_SW_DEVICE_ID);
        XGpio_SetDataDirection(&sw,1,1); //set sw as input port
        XGpio_InterruptEnable(&sw, XPAR_SW_IP2INTC_IRPT_MASK);
        XGpio_InterruptGlobalEnable(&sw);

    xil_printf("Setting up interrupt controller...\r\n");
    for(delay=0;delay<limit;delay++){}; // delay cycle
    XIntc_Initialize(&myIntc, XPAR_INTC_0_DEVICE_ID);

    xil_printf("Register the interrupt...\r\n");
    for(delay=0;delay<limit;delay++){}; // delay cycle
    XIntc_Connect(&myIntc, XPAR_AXI_INTC_0_PUSH_IP2INTC_IRPT_INTR,
                              (XInterruptHandler)pb_int_handler,
                                   &PushBt);
    XIntc_Connect(&myIntc, XPAR_AXI_INTC_0_SW_IP2INTC_IRPT_INTR,
                                  (XInterruptHandler)sw_int_handler,
                                       &sw);

    xil_printf("Enable individual interrupt...\r\n");
    for(delay=0;delay<limit;delay++){}; // delay cycle
    XIntc_EnableIntr(&myIntc,XPAR_PUSH_IP2INTC_IRPT_MASK | XPAR_SW_IP2INTC_IRPT_MASK);

    xil_printf("Start the interrupt controller...\r\n");
    for(delay=0;delay<limit;delay++){}; // delay cycle
    XIntc_Start(&myIntc, XIN_REAL_MODE);
    XIntc_MasterEnable(&myIntc);
    microblaze_enable_interrupts();

    xil_printf("Setting up exceptions...\r\n");
    for(delay=0;delay<limit;delay++){}; // delay cycle
    Xil_ExceptionInit();

    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_M_AXI_I_EXCEPTION,
            (XExceptionHandler)XIntc_InterruptHandler,
                         &myIntc);
    Xil_ExceptionEnable();

    while(1) {
        xil_printf("Entering loop...\r\n");
        for(delay=0;delay<limit;delay++){}; // delay cycle
    }
}

Any help explaining the right interrupt code sequence?

  • I set up the handlers.
  • I initialized the Interrupt controller.
  • I connected the handlers.
  • I enabled interrupt masks.
  • I started the Interrupt Controller.
  • I enabled the Master Interrupt Controller.

So what did I forgot? Or what's wrong? Thanks

gog
  • 1,220
  • 11
  • 30
Gian
  • 41
  • 1
  • 6
  • for record: I find and insterestng papers by Xilinx "Using and creating Interrupt-Based Systems" in two verison 2005 and 2009 (ver3_4) I hoe that help – Gian Oct 27 '14 at 20:03
  • found solution: changing these lines XGpio_InterruptEnable(&PushBt, XPAR_PUSH_IP2INTC_IRPT_MASK); to XGpio_InterruptEnable(&PushBt, 0xff); and XGpio_InterruptEnable(&sw, XPAR_SW_IP2INTC_IRPT_MASK); to XGpio_InterruptEnable(&sw, 0xff); so now code work but I will investigate why :) It's a Interrupt mask problem – Gian Oct 27 '14 at 20:10
  • You can answer your own post and accepted so it will no longer be marked as ''unanswered'' – n0p Nov 14 '14 at 08:23

2 Answers2

0

found solution: changing these lines

XGpio_InterruptEnable(&PushBt, XPAR_PUSH_IP2INTC_IRPT_MASK);

to

XGpio_InterruptEnable(&PushBt, 0xff);

and

XGpio_InterruptEnable(&sw, XPAR_SW_IP2INTC_IRPT_MASK);

to

XGpio_InterruptEnable(&sw, 0xff);

so now code works but I will investigate why :) It's a Interrupt mask problem

Korem
  • 11,383
  • 7
  • 55
  • 72
Gian
  • 41
  • 1
  • 6
0

You are passing wrong values to the Mask parameter of the XGpio_InterruptEnable function.

XPAR_PUSH_IP2INTC_IRPT_MASK and XPAR_SW_IP2INTC_IRPT_MASK are interrupt mask values for the Interrupt Controller peripheral, NOT for the GPIO peripheral.

This is an excerpt from C:\Xilinx\14.7\ISE_DS\EDK\sw\XilinxProcessorIPLib\drivers\gpio_v3_01_a\src\xgpio_l.h, showing you the correct mask values for the GPIO peripheral:

/** @name Interrupt Status and Enable Register bitmaps and masks
 *
 * Bit definitions for the interrupt status register and interrupt enable
 * registers.
 * @{
 */
#define XGPIO_IR_MASK       0x3 /**< Mask of all bits */
#define XGPIO_IR_CH1_MASK   0x1 /**< Mask for the 1st channel */
#define XGPIO_IR_CH2_MASK   0x2 /**< Mask for the 2nd channel */
/*@}*/

So, you should probably change your lines

XGpio_InterruptEnable(&PushBt, XPAR_PUSH_IP2INTC_IRPT_MASK);
XGpio_InterruptEnable(&sw, XPAR_SW_IP2INTC_IRPT_MASK);

to

XGpio_InterruptEnable(&PushBt, XGPIO_IR_CH1_MASK);
XGpio_InterruptEnable(&sw, XGPIO_IR_CH1_MASK);
gog
  • 1,220
  • 11
  • 30