cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Visitor
Visitor
8,144 Views
Registered: ‎02-24-2013

Microblaze Ipcore Interrupt control

Hello,

 

I have just started working with the microblaze IPCore. I work on the spartan3 xs200 board. I have activated the interruption option on the logic IPCore as well as the inputs GPI1 and the outputs GPO1.
 I am only trying to catch an interrupt by software. I have connected one of the switches of the board to the interrupt input. The idea is to increase by one a counter once the interrupt has been catched.

I have been reading a lot of artcles on the net and some forum threads about how to use interrupt in the microblaze. However all the information that I have found is about the older versions of the libraries. I am using ISE 14.3 webpack.

There is no information about how to work with interrupts using the new library XIOmodule.h

 

I am using this C code but it is not working. Can you please help me and tell me what am I doing wrong?

 

#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "xiomodule.h"


u32 cntr;
XIOModule interr1;


void IntHandler(void *InstancePtr)
{
        XIOModule *Interr = (XIOModule *)InstancePtr;
        
                cntr = cntr + 16;
        
        XIOModule_Acknowledge(Interr, 0);
}


int main()
{
    init_platform();

            int Status;
        XIOModule gpo;

        cntr = 0;
            
            // GPO
        Status = XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID);
        Status = XIOModule_Start(&gpo);
        
            // INTERRUPTION
        Status = XIOModule_Initialize(&interr1, XPAR_IOMODULE_0_DEVICE_ID);
        XIOModule_Connect(&interr1, 0, (XInterruptHandler)IntHandler, &interr1);
        XIOModule_Enable(&interr1, 0);
            Status = XIOModule_Start(&interr1);
        
        while (1)
        {
            XIOModule_DiscreteWrite(&gpo, 1, cntr);
        }

        cleanup_platform();

    return 0;
}

 

Thank you in advance for your help and your time.

 

Mario

0 Kudos
5 Replies
Highlighted
Teacher
Teacher
8,141 Views
Registered: ‎11-14-2011

I am using this C code but it is not working

Shall we guess what the problem is or can you tell us what about your design is not working?

 

What steps have you taken to investigate the problem? Have you run the software in debug mode? Have you done any simulations of the system? Have you used chipscope in any way?

 

Regards,

 

Howard

 

----------
"That which we must learn to do, we learn by doing." - Aristotle
0 Kudos
Highlighted
Visitor
Visitor
8,134 Views
Registered: ‎02-24-2013

To debug I have done the following steps.
first of all the gpo is connected to a logical analyzer. it lets me see te value of the 32 outputs of thegI am using a digital analyzer in order to know the GPO1. I see that the counter is always zero, in never increases. I cant run the software in the debug mode because even with the best optimization on the compilation, the code is to big for size memory selected. so i use the release mode.
I thought that the problem could be on the initialize function but it returns 0 (XST_SUCCESFUL). the start function also returns 0.
then i have started reading internal registers such as irq_sts or irq_pending to find exactly where is the problem. as a result i have found that even if i had enable the interruption with theenable function, the sts register and the pending register were not the same after interruptons happened. it means that in the irq_enable register the bit 16 is not set to 1 to enable the interruption 0.
i have done a test where i have writen directly xFFFFFFFF on the enable register and then i found tha same value on the sts and pending registers after the interruption happens.
as you have suggested, can i run the software separetly to debug it simulating the inputs behaviour and inspecting the outputs?? how can i do it? i have never used chipscope.

thank again Howard
mario
0 Kudos
Highlighted
Teacher
Teacher
8,130 Views
Registered: ‎11-14-2011

 I cant run the software in the debug mode because even with the best optimization on the compilation, the code is to big for size memory selected

Can't you trim the software down, just for test purposes, so that only the interrupt functions are used? How much memory have you selected for the MicroBlaze?

 

My suggestion was to use the debugger for the software on the live hardware, as this will give you the most definitive functional performance of the software in the system.

 

If you are using an external logic analyser, there may be no need to introduce chipscope, as they may be doing the same thing (although chipscope will give you better access to internal signals). The use of chipscope is so vast that I couldn't possibly do it justice in a forum post, you would be much better searching for the user guide on the Xilinx site.

 

Looking at your code, I think I might handle it a little differently (not that you are "wrong") because I'm not so comfortable with the way that the loop runs.

 

I would consider, using pseudo-code, something more like this:

 

// interrupt handler

  if (interrupt)

    clear_interrupt();

 

// main code

  status = gpio_initialise();

  status = gpio_start();

 

  // inifinite loop

    while (1) {

      // write data to force interrupt condition

      gpio_write(data);

      while (!interrupt_condition) {

      // do nothing

      }

      // interrupt occurred, increase count

        counter = counter + 1;

        // clear gpio data value if required

        // print counter value to terminal if required

    }

 

  return 0;

 

The principle differences being that the handler only acknowledges the interrupt and no activities are undertaken while you are waiting for an interrupt to occur. This may not be the most efficient code but it may let you investigate where in the overall loop your problems are occurring. However, I am not a C expert, so may be this can be taken with a pinch of salt :)

 

Regards,

 

Howard

 

----------
"That which we must learn to do, we learn by doing." - Aristotle
0 Kudos
Highlighted
Visitor
Visitor
8,116 Views
Registered: ‎02-24-2013

Thank you for your answer Howard,

 

but your solutions is not working neither.

 

I think I am missing any function that shall connect the XIOModule variables with the HW registers.

I say that because normally this line shall create a variable to contain all the interruption information:

XIOModule interr1;

 

the initialize function returns 0.

data = XIOModule_Initialize(&interr1, XPAR_IOMODULE_0_DEVICE_ID);

It means that &interr1 is not NULL and it is not still started. After this function I see that the interr1.IsReady is set to 1, the interr1.BaseAddress= 0x80000000.  The interr1.IsStarted=0.

 

Then I enable the interruption avec the following function:

XIOModule_Enable(&interr1, 0);

Then the interr1.CurrentIER=0x00010000. It means that the interruption 0 is enabled according to the XIOModule variable.

Nevertheless, the register IRQ_ENABLE (0x80000038)= 0x00000000. This register is W only, but if you compare the IRQ_STATUS and the IRQ_PENDING you can obtain the value of the IRQ_ENABLE (IRQ_PENDING= IRQ_STATUS & IRQ_ENABLE). On my test the IRQ_STATUS=0x00010000 and the IRQ_PENDING = 0x00000000.

 

That's why I think that there is no connexion between the XIOModule variable interr1 and the HW registers.

 

Have you any idea about how to fix this or which is the function missing?

 

Thank you in advanced,

 

Mario

 

 

 

 

int main()
{
    init_platform();

        int data;
        XIOModule gpi;
        u32 * REG_INTC_STS_PTR;
        u32 * REG_INTC_PENDING_PTR;
        u32 * REG_INTC_EN_PTR;
        u32 * REG_INTC_ACK_PTR;
        u32 reg_IntcSts;

        REG_INTC_STS_PTR =  (u32 *)REG_IRQ_STS_ADD;
        REG_INTC_PENDING_PTR = (u32 *)REG_IRQ_PENDING_ADD;
        REG_INTC_EN_PTR = (u32 *)REG_IRQ_EN_ADD;
        REG_INTC_ACK_PTR = (u32 *)REG_IRQ_ACK_ADD;

        cntr = 4;

        microblaze_enable_interrupts();

        data = XIOModule_Initialize(&gpi, XPAR_IOMODULE_0_DEVICE_ID);
        data = XIOModule_Start(&gpi);
        data = XIOModule_Initialize(&gpo, XPAR_IOMODULE_0_DEVICE_ID);
        data = XIOModule_Start(&gpo);
        //data = XIOModule_Initialize(&timer, XPAR_IOMODULE_0_DEVICE_ID);

        // Initialize the timer counter so that it's ready to use.
        //Status = XIOModule_Timer_Initialize(&timerp, XPAR_IOMODULE_0_DEVICE_ID);
        data = XIOModule_Initialize(&interr1, XPAR_IOMODULE_0_DEVICE_ID);

0 Kudos
Highlighted
Teacher
Teacher
8,100 Views
Registered: ‎11-14-2011

I have not used the microblaze as an instantiated coregen part, only through developing it in XPS, so I am very unsure of the workings of the XIOModule that you write of. Subsequently, I can only offer further, rather general, advice.

 

1. What you last wrote of and the code you attached seem have only a tenuous link - I could not understand the relevance.

2. Without checking, I would guess that the API for the XIOModule is documented, usually as comments in the supplied C files. I suggest reading through these to determine exactly what functions you need and how to use them.

3. You have not mentioned exactly what isn't working in my previous suggestions.

4. For some other Xilinx apps, enabling the interrupts only works if a Global Interrupt Enable is set. Can this be done and are you doing it?

 

Apologies for the rather vague response but I'm heading out of my sphere of knowledge now.

----------
"That which we must learn to do, we learn by doing." - Aristotle
0 Kudos