cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Observer
Observer
7,306 Views
Registered: ‎01-26-2011

Petalinux using interrupt from Fixed Interval Timer

I'm new to Petalinux and I'm having trouble getting two interrupts to work. I haven't had much luck in my Internet searches.

 

I have two Fixed Interval Timers and two CDMA cores connected to the IRQ_F2P input on the Zynq Processing System like so:

 

FIT IRQ 1.jpg

 

After building and running Petalinux I see the two CDMA interrupts:

 

root@bmdl_sdr0:/# cat /proc/interrupts
CPU0 CPU1
27: 0 0 GIC 27 gt
29: 26788 22922 GIC 29 twd
35: 0 0 GIC 35 f800c000.ocmc
39: 43 0 GIC 39 f8007100.adc
40: 0 0 GIC 40 f8007000.devcfg
41: 0 0 GIC 41 f8005000.watchdog
43: 869209 0 GIC 43 ttc_clockevent
45: 0 0 GIC 45 f8003000.dmac
46: 0 0 GIC 46 f8003000.dmac
47: 0 0 GIC 47 f8003000.dmac
48: 0 0 GIC 48 f8003000.dmac
49: 0 0 GIC 49 f8003000.dmac
51: 0 0 GIC 51 e000d000.spi
53: 0 0 GIC 53 ehci_hcd:usb1
54: 4 0 GIC 54 eth0
56: 35 0 GIC 56 mmc0
59: 441 0 GIC 59 xuartps
63: 0 0 GIC 63 xilinx-cdma-controller
64: 0 0 GIC 64 xilinx-cdma-controller
72: 0 0 GIC 72 f8003000.dmac
73: 0 0 GIC 73 f8003000.dmac
74: 0 0 GIC 74 f8003000.dmac
75: 0 0 GIC 75 f8003000.dmac
IPI1: 0 535 Timer broadcast interrupts
IPI2: 6125 5399 Rescheduling interrupts
IPI3: 0 0 Function call interrupts
IPI4: 50 59 Single function call interrupts
IPI5: 0 0 CPU stop interrupts
IPI6: 0 0 IRQ work interrupts
IPI7: 0 0 completion interrupts
Err: 0

 

But I don't see the FIT timers which should be on GIC 61 and 62. I assume I need to add something to the Device Tree but I'm not sure how to go about it.

 

How do I get these two interrupts visible to Petalinux? I assume the solution would also apply to any signal used as an interrupt that is coming into the "system" from an external source.

 

Thank you,

 

Kevin

 

0 Kudos
1 Reply
Highlighted
Visitor
Visitor
7,217 Views
Registered: ‎06-16-2014

Re: Petalinux using interrupt from Fixed Interval Timer

Hi

 

Did you ever get an answer to your question?

 

I am new to writing drivers for the zynq and have put together the following hardware to get me started. Below the diagram is my driver code which when I use insmod and then mknod installs OK. Using cat /proc/interrupts I can see the interrupt at the required number but the values stay at zero indicating no interrupts have been produced.  I have tried a few different interrupt numbers i.e. (91+32) 91 and (91-32) but none of them work. I have also written a small bit of c code to open the driver, which it does, but still no numbers in the /proc/interrupts.  I am using Vivado 2014.4 and petalinux 2014.4 on the microzed board

 

I would be very grateful if you or anyone else out there could give me a hand

 

Thanks

Steve

 

design_2_small.jpg

 

 

 

/*  mydriverdrv.c - The simplest kernel module.
 */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/interrupt.h>

#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>

#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/cdev.h>

#define DRIVER_NAME "mydriverdrv"
#define MAX_LENGTH  4000

/* Standard module information, edit as appropriate */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sko");
MODULE_DESCRIPTION("mydriverdrv - loadable module template generated by petalinux-create -t modules");


/* Globals */
static char  CharDeviceBuf[MAX_LENGTH];
static int   BufferPtr = 0;
dev_t        MyDevNumber;
struct cdev *Mycdev;
int          Inuse = 0; /* Keep count of how many times the driver is open */


static irqreturn_t mydriverdrv_irq(int irq, void *lp)
{
 printk("mydriverdrv interrupt\n");
 return IRQ_HANDLED;
}

 

ssize_t mydriverdrv_read(struct file *pFile, char __user *pBuffer, size_t Length, loff_t *pOffset)
{
    int NumBytesCopied;
    int NumBytesNotCopied;


    /* When the driver buffer is empty we must return 0 so check first for a zero buffer size */
    if(BufferPtr == 0)
    {
        return 0;
    }

    /* If the user wants to read more bytes than have been placed in the buffer we need */
    /* to reduce the Length so it fits in the driver buffer                             */
    if(Length > BufferPtr)
    {
         Length = BufferPtr;
    }

    /* Copy the number of bytes specified in Length from the drivers local buffer CharDeviceBuf */
    /* to the user space buffer pBuffer.                                                        */
    /* (Destination, Source,Length)                                                             */
    NumBytesNotCopied = copy_to_user(pBuffer, CharDeviceBuf, Length);

    /* Work out if we have not copied all the requested bytes */
    NumBytesCopied = Length - NumBytesNotCopied;

    /* Update the buffer pointer BufferPtr */
    BufferPtr -= NumBytesCopied;
   
    /* Tell the OS how many bytes we have copied */
    *pOffset += NumBytesCopied;

    printk (KERN_INFO "\n Writen data from app %s , nbytes=%d\n",CharDeviceBuf,NumBytesCopied);

    /* Send back the number of unwriten bytes */
    return NumBytesCopied;


}

ssize_t mydriverdrv_write(struct file *pFile, const char __user *pBuffer, size_t Length, loff_t *pOffset)
{

    int NumBytesCopied;
    int NumBytesNotCopied;
    int BytesLeftInCharDeviceBuf;


    /* Protect against buffer overflow */
    if(Length > MAX_LENGTH)
    {
        Length = MAX_LENGTH;
    }

  
    /* Copy the number of bytes speified in Length from the user space buffer pBuffer     */
    /* into the drivers local buffer CharDeviceBuf. Use                                   */ 
    /* (Destination, Source,Length)                                                       */
    NumBytesNotCopied = copy_from_user(CharDeviceBuf, pBuffer, Length);

    /* Work out howmany bytes were really copied */
    NumBytesCopied = Length - NumBytesNotCopied;
   
    /* Update the buffer pointer BufferPtr */
    BufferPtr = NumBytesCopied;

    /* Tell the OS how many bytes we have copied */
    *pOffset += NumBytesCopied;

    printk (KERN_INFO "\n Rec'vd data from app %s , nbytes=%d\n",CharDeviceBuf,NumBytesCopied);

    /* Send back the number of unwriten bytes */
    return NumBytesCopied;

}


// unsigned int (*poll) (struct file *, struct poll_table_struct *);

int mydriverdrv_open(struct inode *pInode, struct file *pFile)
{
    /* Only allow one version of the driver to be open */
    if(Inuse >= 1)
    {
        printk(KERN_INFO "\nDevice busy %s\n",DRIVER_NAME);
        return -EBUSY;
    }   

    /* If we have not got a version of the driver open then allow it but set the */
    /* Inuse variable to one so we don't open another one.                       */
    Inuse = 1;

    printk(KERN_INFO "Open operation invoked \n");

    return 0;

}

// int (*flush) (struct file *, fl_owner_t id);

int mydriverdrv_release(struct inode *pInode, struct file *pFile)
{

    /* Let someone else open the driver */
    Inuse = 0;

    return 0;
}

 


/* Create the structure which maps the functions to the standard driver calls */
static struct file_operations char_dev_fops =
{
    .owner   = THIS_MODULE,
    .read    = mydriverdrv_read,
    .write   = mydriverdrv_write,
    .open    = mydriverdrv_open,
    .release = mydriverdrv_release
};

static int __init mydriverdrv_init(void)
{
        int Ret;
        unsigned int IrqNumber = (91 - 32); //(91 + 32);
        unsigned long IrqFlags  = IRQF_NO_SUSPEND;

 printk("amrammdrv init.\n");

        /* Produce a structure with the Major and Minor numbers in */
        MyDevNumber = MKDEV(89,0); /* Major = 89, Minor = 0 */

        /* Register the device number with the kernel */
        register_chrdev_region(MyDevNumber, 1, DRIVER_NAME);


        /* Allocate space for the device driver structure */
        Mycdev = cdev_alloc();

        /* Initialise the device drivr structure with the map of dunctions to standard calls structure */
        cdev_init(Mycdev, &char_dev_fops);

        /* Tell the kernel to map the device driver structure and the device number together */
        Ret=cdev_add(Mycdev, MyDevNumber, 1);
   
        /* Do some error handling */
        if(Ret < 0 )
        {
           printk("Error registering device driver\n");
           return Ret;
        }
        printk(KERN_INFO"\nDevice Registered %s\n",DRIVER_NAME); 
   
        /* Clear a versiable array used to store read write data in this driver */
        memset(CharDeviceBuf,'\0',MAX_LENGTH);


        /* Register an IRG handler for the User-push button press event */
 
        Ret = request_irq(IrqNumber, &mydriverdrv_irq, IrqFlags, "mydriverdrv", NULL);
        if (Ret < 0)
        {
            printk(KERN_ALERT "%s: request_irq failed with %d\n",__func__, Ret);
        }

 


 return 0;
}

static void __exit mydriverdrv_exit(void)
{
     /* Tidy up all the data used in this driver */
     cdev_del(Mycdev);
     unregister_chrdev_region(MyDevNumber,1);
     printk(KERN_INFO "\n Driver unregistered \n");
}

 

module_init(mydriverdrv_init);
module_exit(mydriverdrv_exit);

 

0 Kudos