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: 
Highlighted
Visitor brogath
Visitor
16,599 Views
Registered: ‎07-09-2013

AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

While this hardware and application work fine using the bare metal example, im trying to do the same as a linux application but i dont really know what to do to get this working.

 

Right now i have a program that uses mmap to map the timer's registers to user-space and i seem to be able to configure it as no errors occur during these operations.

 

Additionally, i use this driver:

http://pastebin.com/Huhpuk1s

but with only a single IO recourse mapped as the timer:

{

  .start = 0x42800000,

  .end = 0x4280ffff,

  .name = "axi_timer_0"

  .flags = IORECOURCE_MEM

},

and i addded a printk inside the interrupt handler

 

I can compile and insert this module without problems (although unloading causes some kernel problems)

For kernel i compiled from the linux-digilent tree with digilent_zed_defconfig.

 

I think i am missing a part somewhere beacuse the printk does not show up after configuring the timer but i have never worked with device drivers or linux-interrupts so i can't figure out what i am missing.

 

Any suggestions, or perhaps a example would be much appreciated,

Thanks in advance

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
Visitor brogath
Visitor
22,170 Views
Registered: ‎07-09-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

combining the available recourses i have managed to complete a solution. as usual the problem was not too far from where i started but i initialized the timer wrong among a few other minor issues.

 

I have attached the final solution i have used to test the Zynq's interrupt latency. it could use a bit less but it uses system calls to activate and disable the timer.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <linux/fs.h>		//required for fops
#include <linux/uaccess.h>	//required for 'cpoy_from_user' and 'copy_to_user'
#include <linux/signal.h>	//required for kernel-to-userspace signals

MODULE_LICENSE("GPL");

#define IRQ_NUM		90		// interrupt line
#define TIMER_BASE	0x42800000

#define TIMER_SIZE	0x0000FFFF
#define TCSR0		0x00000000
#define TLR0		0x00000004
#define TCR0		0x00000008
#define T0INT		0x00000100

#define TIMER_TCSR0	0x42800000	// address of timer 0's control and status register
#define TIMER_TLR0	0x42800004	// address of timer 0's load register
#define TIMER_TCR0	0x42800008	// address of timer 0's counter register
#define LOAD_VAL	0xE2329AFF	// address load value (500000000 cycles) ~5 sec
unsigned long *pTIMER_TCSR0;		// pointer to timer 0 control and status register
unsigned long *pTIMER_TLR0;		// pointer to timer 0 load register
unsigned long *pTIMER_TCR0;		// pointer to timer 0 counter register

#define DEVICE_NAME "syscall"		// device name
#define SYSCALL_MAJOR 22		// device major number
#define BUF_LEN 80			// max buffer length
#define SUCCESS 0			// success return value

//unsigned long *pSYSCALL_Virtual;	// base address
static int Device_Open = 0;		// device status

static char msg[BUF_LEN];		// the msg the device will give when asked
static char *msg_Ptr;
static int intcount;

// write routine (called when write() is used in user-space)
ssize_t syscall_write(struct file *flip, const char *buf, size_t length, loff_t *offset)
{
	printk("syscall_write.\n");				// debug: procedure call message
	if (copy_from_user(msg, buf, length) != 0)		// read buffer from user space
		return -EFAULT;					// return error if it failed
	printk("Received: %s \n",msg);				// debug: what string is received

	if (strcmp(msg,"1") == 0)				// enable timer command
	{
		printk("Driver enables timer.\n");		// print timer status message
		iowrite32(LOAD_VAL,pTIMER_TLR0);		// prepare timer cycle 
		iowrite32(0x000000B0,pTIMER_TCSR0);		// load the load-register
		iowrite32(0x000000D0,pTIMER_TCSR0);		// Generate mode,upcounter, reload generate value
								// no load, enable IRQ, enable Timer
		return SUCCESS;					// return 0 to application
	} 
	else if (strcmp(msg,"0") == 0)				// disable timer command
	{
		printk("Driver disables timer.\n");		// print timer status message
		iowrite32(0x00000050,pTIMER_TCSR0);		// Generate mode, upcounter, reload generate value
								// no load, enable IRQ, disable Timer
		return SUCCESS;					// return 0 to application
	} 
	else 
	{
		printk("Driver received wrong value.\n");	// Print error message
		return -EFAULT;					// unknown value received
	}
}

// read routine (called when read() is used in user-space)
ssize_t syscall_read(struct file *flip, char *buf, size_t length, loff_t *offset)
{
	unsigned long timerval;
	// read timer value

	printk("syscall_read.\n");				// debug: procedure call message
	timerval = ioread32(pTIMER_TCR0);
	printk("Read() call value : %lu Cycles\n",timerval);	// display timer value
	
	if (copy_to_user(buf, &msg, length) != 0)		// send counter value
		return -EFAULT;
	else 
		return 0;
}

// open routine (called when a device opens /dev/syscall)
static int syscall_open(struct inode *inode, struct file *file)
{
	if (Device_Open)					// if the device is allready open,
		return -EBUSY;					// return with an error

	Device_Open++;						// 'open' device
	sprintf(msg,"You tried to open the syscall module.\n");	// print open message
	msg_Ptr = msg;						
	try_module_get(THIS_MODULE);
	return 0;
}

// close routine (called whne a device closes /dev/syscall)
static int syscall_close(struct inode *inode, struct file *file)
{
	Device_Open--;						// 'close' device

	module_put(THIS_MODULE);
	return 0;
}

// device init and file operations
struct file_operations syscall_fops = {
	.read = syscall_read,		// read()
	.write = syscall_write,		// write()
	.open = syscall_open,		// open()
	.release = syscall_close,	// close()
};

// timer interrupt handler
static irqreturn_t irq_handler(int irq,void*dev_id)		
{      
	unsigned long temp;
	unsigned long timervalue;
      
	timervalue = ioread32(pTIMER_TCR0);			// Read Timer/Counter Register
	printk("Interrupt! Timer counter value : %lu Cycles\n",(timervalue-LOAD_VAL));	// Display timer value

	temp = ioread32(pTIMER_TCSR0);				// clear timer IRQ
	temp |= T0INT;
	iowrite32(temp, pTIMER_TCSR0);

	intcount++;
	if (intcount>=100)					// after 100 interrupts
	{
		printk("100 interrupts have been registered.\nDisabling timer");// print timer status message
		iowrite32(0x00000050,pTIMER_TCSR0);		//disable timer;
	}

	return IRQ_HANDLED;
}

// init module      
static int __init mod_init(void)  
{
	unsigned long temp;
	printk(KERN_ERR "Init syscall module. \n");

	if (request_irq(IRQ_NUM,irq_handler,IRQF_DISABLED, DEVICE_NAME, NULL))  //request timer interrupt
	{
		printk(KERN_ERR "Not Registered IRQ. \n");
		return -EBUSY;
	}
	printk(KERN_ERR "Registered IRQ. \n");

	pTIMER_TCSR0 = ioremap_nocache(TIMER_TCSR0,0x4);	// map timer 0 control and status register
	pTIMER_TLR0 = ioremap_nocache(TIMER_TLR0,0x4);		// map timer 0 load register
	pTIMER_TCR0 = ioremap_nocache(TIMER_TCR0,0x4);		// map timer 0 count register
	//iowrite32(LOAD_VAL, pTIMER_TLR0);			// place load value in load register
	//temp = ioread32(pTIMER_TLR0);				// debug: read load value to check
	//printk("Load value: %lu.\n",temp);			// debug: print the read load value
	//iowrite32(0x000000B0, pTIMER_TCSR0);			// load TLR
	//iowrite32(0x000000D0, pTIMER_TCSR0);			// Generate mode,downcounter,reload generate
								// value,no load,enable IRQ,enable Timer
	intcount = 0;						// set interrupt count to 0, driver will unload on 100 interrupts
	// manual node creation
	if (register_chrdev(SYSCALL_MAJOR, DEVICE_NAME, &syscall_fops))
		printk("Error: cannot register to major device 22.\n");
	
	printk("Type: mknod /dev/%s c %d 0\n",DEVICE_NAME, SYSCALL_MAJOR);
	printk("And remove it after unloading the module.\n");

	return SUCCESS;
} 

// exit module
static void __exit mod_exit(void)  		
{
	iounmap(pTIMER_TCSR0);				// unregister timer hardware
	iounmap(pTIMER_TLR0);
	iounmap(pTIMER_TCR0);
	free_irq(IRQ_NUM, NULL);			// unregister timer interrupt
	unregister_chrdev(SYSCALL_MAJOR, "syscall");	// unregister device
	printk(KERN_ERR "Exit syscall Module. \n");	// print unload message
}

module_init(mod_init);
module_exit(mod_exit);

MODULE_AUTHOR ("Tom");
MODULE_DESCRIPTION("Testdirver for the Xilinx AXI Timer IP core & system calls.");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("custom:syscall");

 

 

thanks for the help and have a nice day

0 Kudos
17 Replies
Xilinx Employee
Xilinx Employee
16,592 Views
Registered: ‎03-13-2012

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

I did something similar a while back. It was certainly not perfect, but it did work for me at that time. I don't know if it helps, but in case you can take a look at the module I used here http://pastebin.com/iW4BD8eL .

0 Kudos
Visitor brogath
Visitor
16,579 Views
Registered: ‎07-09-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

Thank you for your responce. 

 

I have taken a look at your module but im not able to compile it yet. i am missing the last include, uioDrv.h

 

Presumably, this one hold all the addresses and offsets for the timer looking at the undeclared variables.

I should be able to replace it with their respective values but it just takes a while to get it all right.

 

Ill post my results once im done.

 

Btw, does this module make a node in /dev? 

So then i should open the node /dev/uioX in my user-space program to access the open and release procedures?

0 Kudos
Xilinx Employee
Xilinx Employee
16,570 Views
Registered: ‎03-13-2012

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

That module had a dependency to another one. As I said, it was not pretty and a while ago. I thought it might include something to help you fix up yours. I'm not sure taking mine will work.

 

The header file does only contain some #defines (and shoud rather be part of the .c). This are its contents:

#ifndef __UIODRV_H__                                                             
#define __UIODRV_H__                                                             
                                                                                 
#define DEVICENAME "XIL_AXI_COUNTER"                                             
#define DRVVERSION "0.0.1"                                                       
#define TIMERBAR  0x51001000                                                     
#define IOREGIONSIZE 28                                                          
                                                                                 
#define TC0_CS_REG      0                                                        
#define TC0_RLD_REG     4                                                        
#define TC0_TC_REG      8                                                        
#define TC1_CS_REG      0x10                                                     
#define TC1_RLD_REG     0x14                                                     
#define TC1_TC_REG      0x18                                                     
                                                                                 
#define TC_MDT0         1<<0                                                     
#define TC_UDT0         1<<1                                                     
#define TC_GENT0        1<<2                                                     
#define TC_CAPT0        1<<3                                                     
#define TC_ARHT0        1<<4                                                     
#define TC_LOAD0        1<<5                                                     
#define TC_ENIT0        1<<6                                                     
#define TC_ENT0         1<<7                                                     
#define TC_T0INT        1<<8                                                     
#define TC_PWMA0        1<<9                                                     
#define TC_ENALL        1<<10                                                    
                                                                                 
#endif

 

0 Kudos
Visitor brogath
Visitor
16,552 Views
Registered: ‎07-09-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

Ah yes, i noticed now your example is a modification of the existing uio_pdrv_genirq.c existing in the digilent kernel tree.

 

Adding the header file allows it to be compiled with an error on the ui_register_device.

I noticed this was becasue the kernel is not configured with uio.

Adding the uio module to the kernel allows the new module to be compiled without warnings and even inserted on runtime. sadly, it does not work.

 

I added printk messages throughout the driver and even though it loads, the probe procedure is never called.

the only printk's i get are from _init and _exit...

is it required to include this module into the kernel when building a new one? i thought you could basically inmod anything you liked :P

 

making modules is more complex than i thought, ill take another look at some examples.

0 Kudos
Xilinx Employee
Xilinx Employee
16,545 Views
Registered: ‎03-13-2012

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

Please, don't try to get it running with my code. It's really old and I think some things changed.

To trigger the probe a matching platform device needs to be present.  Back in those days I used this second module for this:

#include <linux/init.h>                                                          
#include <linux/module.h>                                                        
#include <linux/platform_device.h>                                               
#include <linux/slab.h>                                                          
                                                                                 
#define DEVICENAME "FABRICPARENT"                                                
MODULE_LICENSE("Dual BSD/GPL");                                                  
MODULE_AUTHOR("Xilinx");                                                         
                                                                                 
static struct platform_device *pdev;                                             
                                                                                 
static int xuio_init(void)                                                       
{                                                                                
                                                                                 
                                                                                 
    printk(KERN_INFO "Adding platform device: %s\n", DEVICENAME);                
                                                                                 
    pdev = platform_device_register_simple(DEVICENAME, 0, NULL, 0);              
         if (pdev == NULL) {                                                     
        printk(KERN_WARNING "Adding platform device \"%s\" failed\n", DEVICENAME);
        kfree(pdev);                                                             
        return -ENODEV;                                                          
    }                                                                            
                                                                                 
    return 0;                                                                    
}                                                                                
                                                                                 
static void xuio_exit(void)                                                      
{                                                                                
   platform_device_unregister(pdev);                                             
   kfree(pdev);                                                                  
}                                                                                
                                                                                 
                                                                                 
module_init(xuio_init);                                                          
module_exit(xuio_exit);

 But I think, today this should be possible to be driven through the device tree. My code is really old and predates the DT migration of Zynq.

0 Kudos
Visitor brogath
Visitor
22,171 Views
Registered: ‎07-09-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

combining the available recourses i have managed to complete a solution. as usual the problem was not too far from where i started but i initialized the timer wrong among a few other minor issues.

 

I have attached the final solution i have used to test the Zynq's interrupt latency. it could use a bit less but it uses system calls to activate and disable the timer.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <linux/fs.h>		//required for fops
#include <linux/uaccess.h>	//required for 'cpoy_from_user' and 'copy_to_user'
#include <linux/signal.h>	//required for kernel-to-userspace signals

MODULE_LICENSE("GPL");

#define IRQ_NUM		90		// interrupt line
#define TIMER_BASE	0x42800000

#define TIMER_SIZE	0x0000FFFF
#define TCSR0		0x00000000
#define TLR0		0x00000004
#define TCR0		0x00000008
#define T0INT		0x00000100

#define TIMER_TCSR0	0x42800000	// address of timer 0's control and status register
#define TIMER_TLR0	0x42800004	// address of timer 0's load register
#define TIMER_TCR0	0x42800008	// address of timer 0's counter register
#define LOAD_VAL	0xE2329AFF	// address load value (500000000 cycles) ~5 sec
unsigned long *pTIMER_TCSR0;		// pointer to timer 0 control and status register
unsigned long *pTIMER_TLR0;		// pointer to timer 0 load register
unsigned long *pTIMER_TCR0;		// pointer to timer 0 counter register

#define DEVICE_NAME "syscall"		// device name
#define SYSCALL_MAJOR 22		// device major number
#define BUF_LEN 80			// max buffer length
#define SUCCESS 0			// success return value

//unsigned long *pSYSCALL_Virtual;	// base address
static int Device_Open = 0;		// device status

static char msg[BUF_LEN];		// the msg the device will give when asked
static char *msg_Ptr;
static int intcount;

// write routine (called when write() is used in user-space)
ssize_t syscall_write(struct file *flip, const char *buf, size_t length, loff_t *offset)
{
	printk("syscall_write.\n");				// debug: procedure call message
	if (copy_from_user(msg, buf, length) != 0)		// read buffer from user space
		return -EFAULT;					// return error if it failed
	printk("Received: %s \n",msg);				// debug: what string is received

	if (strcmp(msg,"1") == 0)				// enable timer command
	{
		printk("Driver enables timer.\n");		// print timer status message
		iowrite32(LOAD_VAL,pTIMER_TLR0);		// prepare timer cycle 
		iowrite32(0x000000B0,pTIMER_TCSR0);		// load the load-register
		iowrite32(0x000000D0,pTIMER_TCSR0);		// Generate mode,upcounter, reload generate value
								// no load, enable IRQ, enable Timer
		return SUCCESS;					// return 0 to application
	} 
	else if (strcmp(msg,"0") == 0)				// disable timer command
	{
		printk("Driver disables timer.\n");		// print timer status message
		iowrite32(0x00000050,pTIMER_TCSR0);		// Generate mode, upcounter, reload generate value
								// no load, enable IRQ, disable Timer
		return SUCCESS;					// return 0 to application
	} 
	else 
	{
		printk("Driver received wrong value.\n");	// Print error message
		return -EFAULT;					// unknown value received
	}
}

// read routine (called when read() is used in user-space)
ssize_t syscall_read(struct file *flip, char *buf, size_t length, loff_t *offset)
{
	unsigned long timerval;
	// read timer value

	printk("syscall_read.\n");				// debug: procedure call message
	timerval = ioread32(pTIMER_TCR0);
	printk("Read() call value : %lu Cycles\n",timerval);	// display timer value
	
	if (copy_to_user(buf, &msg, length) != 0)		// send counter value
		return -EFAULT;
	else 
		return 0;
}

// open routine (called when a device opens /dev/syscall)
static int syscall_open(struct inode *inode, struct file *file)
{
	if (Device_Open)					// if the device is allready open,
		return -EBUSY;					// return with an error

	Device_Open++;						// 'open' device
	sprintf(msg,"You tried to open the syscall module.\n");	// print open message
	msg_Ptr = msg;						
	try_module_get(THIS_MODULE);
	return 0;
}

// close routine (called whne a device closes /dev/syscall)
static int syscall_close(struct inode *inode, struct file *file)
{
	Device_Open--;						// 'close' device

	module_put(THIS_MODULE);
	return 0;
}

// device init and file operations
struct file_operations syscall_fops = {
	.read = syscall_read,		// read()
	.write = syscall_write,		// write()
	.open = syscall_open,		// open()
	.release = syscall_close,	// close()
};

// timer interrupt handler
static irqreturn_t irq_handler(int irq,void*dev_id)		
{      
	unsigned long temp;
	unsigned long timervalue;
      
	timervalue = ioread32(pTIMER_TCR0);			// Read Timer/Counter Register
	printk("Interrupt! Timer counter value : %lu Cycles\n",(timervalue-LOAD_VAL));	// Display timer value

	temp = ioread32(pTIMER_TCSR0);				// clear timer IRQ
	temp |= T0INT;
	iowrite32(temp, pTIMER_TCSR0);

	intcount++;
	if (intcount>=100)					// after 100 interrupts
	{
		printk("100 interrupts have been registered.\nDisabling timer");// print timer status message
		iowrite32(0x00000050,pTIMER_TCSR0);		//disable timer;
	}

	return IRQ_HANDLED;
}

// init module      
static int __init mod_init(void)  
{
	unsigned long temp;
	printk(KERN_ERR "Init syscall module. \n");

	if (request_irq(IRQ_NUM,irq_handler,IRQF_DISABLED, DEVICE_NAME, NULL))  //request timer interrupt
	{
		printk(KERN_ERR "Not Registered IRQ. \n");
		return -EBUSY;
	}
	printk(KERN_ERR "Registered IRQ. \n");

	pTIMER_TCSR0 = ioremap_nocache(TIMER_TCSR0,0x4);	// map timer 0 control and status register
	pTIMER_TLR0 = ioremap_nocache(TIMER_TLR0,0x4);		// map timer 0 load register
	pTIMER_TCR0 = ioremap_nocache(TIMER_TCR0,0x4);		// map timer 0 count register
	//iowrite32(LOAD_VAL, pTIMER_TLR0);			// place load value in load register
	//temp = ioread32(pTIMER_TLR0);				// debug: read load value to check
	//printk("Load value: %lu.\n",temp);			// debug: print the read load value
	//iowrite32(0x000000B0, pTIMER_TCSR0);			// load TLR
	//iowrite32(0x000000D0, pTIMER_TCSR0);			// Generate mode,downcounter,reload generate
								// value,no load,enable IRQ,enable Timer
	intcount = 0;						// set interrupt count to 0, driver will unload on 100 interrupts
	// manual node creation
	if (register_chrdev(SYSCALL_MAJOR, DEVICE_NAME, &syscall_fops))
		printk("Error: cannot register to major device 22.\n");
	
	printk("Type: mknod /dev/%s c %d 0\n",DEVICE_NAME, SYSCALL_MAJOR);
	printk("And remove it after unloading the module.\n");

	return SUCCESS;
} 

// exit module
static void __exit mod_exit(void)  		
{
	iounmap(pTIMER_TCSR0);				// unregister timer hardware
	iounmap(pTIMER_TLR0);
	iounmap(pTIMER_TCR0);
	free_irq(IRQ_NUM, NULL);			// unregister timer interrupt
	unregister_chrdev(SYSCALL_MAJOR, "syscall");	// unregister device
	printk(KERN_ERR "Exit syscall Module. \n");	// print unload message
}

module_init(mod_init);
module_exit(mod_exit);

MODULE_AUTHOR ("Tom");
MODULE_DESCRIPTION("Testdirver for the Xilinx AXI Timer IP core & system calls.");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("custom:syscall");

 

 

thanks for the help and have a nice day

0 Kudos
Observer ariels1
Observer
16,432 Views
Registered: ‎07-22-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

thanks a lot .

 

the code was much of help.

 

best regards.

 

ari

0 Kudos
Visitor anandvlps
Visitor
16,334 Views
Registered: ‎08-01-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

Are you getting printk messages in irq handler.

I have taken your module and compiled it and inserted this module.

but i am not getting any messages

could you please help me out in this. 

0 Kudos
Visitor brogath
Visitor
16,326 Views
Registered: ‎07-09-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

yes, i get a whole lot of messages from loading the module.

 

http://i259.photobucket.com/albums/hh290/Brogath/syscalldriver_zpsa4a391b1.png?t=1375971477

 

this is an screenshot of my terminal after loading the module, keeping it in for around a minute or so and removing it again after. you should see a couple of messages right after loading it even if the timer doesnt work right.

Now my kernel feels the need to print everything as if they are printf commands, not really sure why.

 

if you get no kernel messages (not even using dmesg) then perhaps your kernel has the opposite from mine :P

 

Either way, you could try to change the printk commans to something else you can see. (or just add more different print commands after one another)

 

now that i think of it, if you just dont have a message from the handler, it could be that the IRQ number is different from yours, for this project the IRQ number has been adjusted as there is another piece of hardware in the FPGA that has the original IRQ requested. worth looking into i'd say.

0 Kudos
Visitor anandvlps
Visitor
8,432 Views
Registered: ‎08-01-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

Hi dear,

 

I followed the following steps:

 

1. connected axi_gpio to GIC (line 91 is connected to GIC)

2. continuously generating interrupt in FPGA (i.e., on axi_gpio generating 1 second clock )

3. generated the dts file (in dts file interrupt number is shown as 59) and bin file

4. booted in the linux environment (with kernel 3.6.0)

5. compiled your module and inserted the module.

6. after loading it is showing the following messages

 

[ 147.170000] Init gpio module. 
[ 147.170000] Registered IRQ. 
[ 147.180000] Type: mknod /dev/gpio c 36 0
[ 147.180000] And remove it after unloading the module.

 

7. it is not showing any irq handler messages.

8. am i missing anything. do i have to do some kind initializations to notify the kernel about interrupts?

 

Please guide me

 

thanks 

 

 

0 Kudos
Visitor brogath
Visitor
8,425 Views
Registered: ‎07-09-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

3. it should be perfect to get 91 (52+32=91) accroding to http://www.wiki.xilinx.com/Zynq+Linux

 

6.

your messages shows that the module is ok but the timer might not be confired.

 

7.

The driver as it's posted requires you to activate the timer by opening the device and writing a 1 to it. (the mknod command creates the file you open & write to from your application)

 

To avoid that process, uncomment the 5 lines in the __init mod_init(void) procedure, this will cause the timer to overflow after 500 milion cycles (for our 100Mhz clock around 5 sec) adjust the #define LOAD_VAL at the top to a higher value to make it overload faster.

In addtion to the current messages, it will print out the laod value it placed inside the timer's load register. This will tell you that you can read &write to the timer without problems.

 

if you get error messages after uncommenting, the mapping process goes wrong (segmentation fault for example) or the hardware is not actuallly there (i had loaded a wrong boot.bin myself a few times)

 

as for .8

after loading the module you could type 'cat /proc/interrupts', it should show the requested irq (91) in the list with the name of the driver behind it as well as the number of times an interrupt has occured since it was requested.

If the IRQ is not listed here, something went wrong with the irqrequest (your message shows this is not the case though) in your case, the number should be 91. if you did not adjust the #define IRQ_NUM at the top of the driver this number would be 90.

If  the number remains at 0, either the interrupt number is incorrect (you could try requesting more/other numbers) or the timer is not confired yet or not correctly configured. uncommenting the lines as descibed should tell you if the timer is present at the location the driver expects it to as well as configuring it if it is.

0 Kudos
Visitor anandvlps
Visitor
8,419 Views
Registered: ‎08-01-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

Thank you very much dear.

Finally it worked. I was giving wrong address values.

now it is working. thank you for your valuable support

 

Anand

0 Kudos
Visitor anandvlps
Visitor
8,395 Views
Registered: ‎08-01-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

Could you explain us how to calculate load vallue?

0 Kudos
Visitor anandvlps
Visitor
8,394 Views
Registered: ‎08-01-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

We got it from the document. 

thank you

0 Kudos
Visitor anandvlps
Visitor
8,361 Views
Registered: ‎08-01-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

Hi Dear,

Now we are trying to connect axi gpio to GIC and generating interrupt on that. (Not using axi timer).

ON linux we are trying to catch it. 

 

Have you tried this one? this also needs any kind of initialization?

0 Kudos
Visitor brogath
Visitor
8,351 Views
Registered: ‎07-09-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

For the project, only the timer interrupt has been tested.

 

You would have to look at the request_irq() command to adapt it to your situation.

I think  the Driver does not care what generated the interrupt, for Linux, it is all coming from the GIC so believe that no matter what interrupt you are trying to catch, the method in the driver/application remains the same.

 

just the name, IRQ number and/or device ID would change.

0 Kudos
Visitor anandvlps
Visitor
8,338 Views
Registered: ‎08-01-2013

Re: AR# 50572 (Axi-timer) interrupts in linux

Jump to solution

Thank you for your suggestion.

 

I figured it out. I need to do some initialization for gpio interrupt.

 

now it is working.

 

Thank you,

 

regards,

 

anand

0 Kudos