2008-08-13 14:42:49     Latency in SPI User Mode Drivers using irq_proc_handler.

Document created by Aaronwu Employee on Aug 8, 2013
Version 1Show Document
  • View in full screen mode

2008-08-13 14:42:49     Latency in SPI User Mode Drivers using irq_proc_handler.

Kiran Kumar B (INDIA)

Message: 60421   

 

Greetings uClinux Team,

 

Configuration

Distribution Used : uClinux-dist-2008R1-RC8  ,    Board :  BF527 Ezkit,     Device Driver :  SPI ( BlackFin as Master)

 

Description of Our Need

We have a need to read the SPI device from the user space , during occurrence of external hardware interrupt at rate of 1ms. We basically want to tie-up the IRQ ( GPIO Port G pin 5)  in the kernel space, with the application's SPI read, with minimal kernel changes.

 

Method that we trying

The interrupts generated in kernel space is transmitted to user space through the proc interface. The main key is that the user mode process is allowed to block on a particular file descriptor and when an interrupt arrives the block is revoked and the process is put to schedule. The interrupts are registered through the function init_irq_proc where the irq’s inturn gets registered and the file /proc/irq/<nnn>/irq is created and the proc file operations of the file are linked with the irq_proc operations.

 

Problem Statement

We have done the modification in ezkit.c  ( /arch / blackfin / mach-bf527 / boards )  by adding an extra  structure member   { BTN_2, GPIO_PG5, 1, " fpga-int : EXINT " }    to the structure    bfin_gpio_key_tables.   With this change we are able to see a new directory in our target boards uClinux  /proc / irq / 92 / < new file > 

After going through the kernel code and the study material for drivers and interrupts , I was not able to  find the "init_irq_proc"  and " proc_irq_handler "  in the kernel. 

 

Please let us know if the present  uClinux kernel supports this method of handling interrupts ?

Is this the right way to go about in accessing the /proc/irq/92 files ?

Kindly lets know if the latency involved in this proc interface method will be high ? We actually need to read the SPI, at max within 300us of the interrupt occurrence.

 

Thank you for your time, for reading through the text.

 

QuoteReplyEditDelete

 

 

2008-08-13 15:07:07     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Mike Frysinger (UNITED STATES)

Message: 60424   

 

userspace spi drivers cannot handle irqs.  i guess you could try and repurpose the gpio keys driver to serve as an interrupt source.

 

i dont know why you talk about init_irq_proc and /proc/irq/ as those are status-only directories.  they do not get used by end applications that want to be woken up by an interrupt.

 

we've never tested the latency on any of these pieces though.  i doubt you'd be able to reliably get 300us response time from userspace.  if you need that kind of time, you'll most likely have to write a kernel driver.  perhaps you'll even need to review the realtime adeos patch.

QuoteReplyEditDelete

 

 

2008-08-14 01:00:51     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Sonic Zhang (CHINA)

Message: 60431   

 

Handler interrupt in user space directly is not supported.

 

If you want to read SPI device after a gpio interrupt occurs, you' d better write a kernel module to handler the gpio interrupt and export a ioctl function for an user application to wait and read the SPI device.

 

 

QuoteReplyEditDelete

 

 

2008-08-14 06:59:44     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Kiran Kumar B (INDIA)

Message: 60466   

 

Thank you , Mike and Sonic

 

The article  that I referred for the Interrupt handling through proc interface is given below: ( link)

 

http://wiki.phiepsilon.org/doku.php?id=user_mode_driver

 

Is this kind of handling supported by uClinux?

 

I agree with you that writing kernel modules is the best solution in terms of latency and performance.

 

As you suggested I will start with writing of the kernel module. From past few days have also read through the kerenl code and study reference. Request you to  please suggest me in which file do I register the new GPIO Port-G pin 5 for interrupt capability? ( presently, I have tried adding it in the ezkit.c.  This is been seen in target's /proc/irq/92 directory. Is this fine ? ) And also please let me the mechanism of transferring the read data from the SPI to user space.

 

 

 

Thank you

 

Kiran

QuoteReplyEditDelete

 

 

2008-08-14 09:43:03     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Mike Frysinger (UNITED STATES)

Message: 60478   

 

that document covers internal details of how the UIO framework works.  it is not something that end users have to do.

 

that said, UIO doesnt seem to build for nommu atm.

 

this document explains how to handle interrupts:

http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:interrupts

QuoteReplyEditDelete

 

 

2008-08-17 13:50:10     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Kiran Kumar B (INDIA)

Message: 60553   

 

Thank you Mike , for confirming on UIO.

 

Please let me know whether my below mentioned thought / approach is correct .

 

I understand that I need to write a 'SPI protocol driver'  ( kernel module ) for my new 'FPGA slave SPI device'.

 

In this driver, I need to register for GPIO interrupt ( this external hardware interrupt occurance every 1ms ). In the Interrupt service routine I need to read the SPI by calling 'spi_message_add_tail( )'  or 'spi_async'  ( of  the file   '  /include / linux / spi / spi.h ' ) The read data from SPI ( every 1ms ) can be stored locally in the kernel space memory.

 

From the user space, the application is going to asynchronously make 'read' system calls from the application theads which run at say 1ms.  I need to have the implementation of  ' fops ' in my new  'SPI protocol driver '  and also handle the user space 'read' system calls to provide the  ALREADY  read data from the SPI ( in kernel space).  I need to use the ' copy_to_user' function in the implementation of the 'read' system call.

 

Having been said my understanding, few question are coming up in my mind !! ( please correct me, if I am wrong in my understanding )

 

Can I use and customize the bfin_spi_adc.c  ( of  . . / drivers / char /  ) , which is a simple SPI frame work ? Can I request for a the GPIO IRQ in this file itself or do I need  to write a separate-new kernel module for my FPGA ?  This doubt arrised because ezkit.c ( of  .. /arch / blackfin / mach-bf527 / boards/  ) has  ' spi_board_info   bfin_spi_board_info [ ] '  structure which already  is addressing many spi devices, in which  ' CONFIG_SPI_ADC_BF533 ' is one among them.  If I write a new kernel module, I need to register as a new 'FPGA SPI protocol driver ' in the board info. Am I right ?  

 

Is the SPI frame work specific to BF533 ? Can I use it without any modifications for BF527 ?

 

Or say for reference if I take the  ' linux-2.6x / drivers / input / touchscreen / ad7877.c'  SPI file and modify / customize for my FPGA SPI driver , How will I transfer the read data in the 1ms IRQ to my user space who needs data ? Should I add the 'fops' into this customized file and copy the information to the user on 'read' system call ?

 

Please correct me in my understanding and request you to suggest me the approach to take.

 

Greetings , - Kiran

QuoteReplyEditDelete

 

 

2008-08-18 20:02:40     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Mike Frysinger (UNITED STATES)

Message: 60602   

 

that sounds reasonable in general

 

dont modify existing drivers ... copy them to a new file and customize it for your needs

 

the "BF533" in the config name is a historical artifcat ... the SPI framework works fine for all Blackfins

 

when copying drivers, you should use something that is similar to your device ... the spi adc driver sounds a lot closer than a touchscreen driver

QuoteReplyEditDelete

 

 

2008-08-19 05:25:23     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Kiran Kumar B (INDIA)

Message: 60636   

 

Thank you for the comments Mike... 

 

with spidev.c as reference I have started experimenting the kernel code.

 

Now I am able to create a kernelThread , which waits for event from the IRQ.  I have also registered for a GPIO's IRQ  ( a button of eval board Ezkit BF527 ) , which calls wake_up_interruptible ( ).On a button press from user, I am able to enter the kernel thread. 

 

In this kerenel thread I need to call the spi_read.  But without having the filp and inode, I am not able to do a successful do a spi_read.  Its giving kernel panic !! 

 

I do not have any user space application running. I am just trying to test the kernel for spi_read on occurance of an interrupt. Since the open device is not called from user space. I have copied a part of driver's open code to module init.  After doing this also kerenel panic occured immediately after boot-up , since module init  is called at boot.

 

How will I do a read spi device in the device driver's kthread , without getting struct file *filp information from the user ? How do I get rid of the kernel panic ?

 

- Kiran

 

 

 

 

 

 

QuoteReplyEditDelete

 

 

2008-08-19 11:02:04     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Mike Frysinger (UNITED STATES)

Message: 60652   

 

you only have those structures when opening files or working with character devices.  you arent, so you wont have any of those.

 

then again, you dont need any file pointers to simply do spi reads/writes.  just create your buffers locally.

QuoteReplyEditDelete

 

 

2008-08-19 11:44:33     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Kiran Kumar B (INDIA)

Message: 60657   

 

I tried taking a local backup of struct  inode  and struct  filp in the function spi_devopen  of spidev.c  ( to use it in the spi_read call  called from kthread)  but kernel panic comes..!!   Do you feel this way should actually work.. ?

QuoteReplyEditDelete

 

 

2008-08-19 13:23:38     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Mike Frysinger (UNITED STATES)

Message: 60661   

 

no, that wont work at all.  why are you muckin about with files anyways ?  if your point is to catch an interrupt and then read/write some SPI data, you dont need any files to do that.

QuoteReplyEditDelete

 

 

2008-08-19 14:26:18     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Kiran Kumar B (INDIA)

Message: 60665   

 

yes, my point is to catch an interrupt and then read/write some SPI data...

 

my new kthread code is in spidev.c ( just for testing ).  Below is the code,  in Bold is the code addition by me..

 

 

 

int fpga_irq(int irq, void *dev_id, struct pt_regs *regs)

 

{

 

printk("<1>IRQ ! \n");

 

cond = 1;

 

wake_up_interruptible( &my_waitqueue);

 

return IRQ_HANDLED;

 

}

 

 

 

/*------------------------------FPGA KTHREAD---------------------------------*/

 

 

 

static void fpga_kthread ()

 

{

 

struct spidev_data *spidev;

 

struct spi_device *spi;

 

ssize_t status = 0;

 

unsigned int count = 30; /* number of bytes read from FPGA */

 

int done =0;

 

while(!done)

 

{

 

wait_event_interruptible(my_waitqueue, (cond == 1) );

 

/* do something : read spi */

 

printk("<1>Thread Entered \n");

 

cond = 0;

 

/* -------------------READ ----------------*/

 

/* chipselect only toggles at start or end of operation */

 

 

 

spidev = backup_filp->private_data; /* filp saved from function open*/

 

spi = spidev->spi;

 

mutex_lock(&spidev->buf_lock);

 

status = spi_read(spi, spidev->buffer, count);

 

mutex_unlock(&spidev->buf_lock);

 

 

 

/* -------------------READ END ----------------*/

 

} /* end of while */

 

} /* end of thread */

 

 

 

/*------------------------FPGA KTHREAD END-----------------------------------*/

 

 

 

 

 

 

 

static int __init spidev_init(void)

 

{

 

int status;

 

int result; /* Kiran */

 

struct spidev_data *spidev;

 

struct file *filp;

 

struct inode *inode;

 

 

 

/* Claim our 256 reserved device numbers. Then register a class

 

* that will key udev/mdev to add/remove /dev nodes. Last, register

 

* the driver which manages those device numbers.

 

*/

 

/* Addition by Kiran for */

 

result = request_irq(IRQ_PG0, (void*) fpga_irq, IRQF_TRIGGER_HIGH, "Fpga_spi_irq", NULL);

 

if(result)

 

printk(KERN_NOTICE "Error %d requesting IRQ \n",result);

 

init_waitqueue_head(&my_waitqueue);

 

kernel_thread( fpga_kthread, NULL, 0 );

 

 

 

/* end */

 

.............

 

static int spidev_open(struct inode *inode, struct file *filp)

 

{

 

struct spidev_data *spidev;

 

int status = -ENXIO;

 

mutex_lock(&device_list_lock);

 

list_for_each_entry(spidev, &device_list, device_entry) {

 

if (spidev->dev.devt == inode->i_rdev) {

 

status = 0;

 

break;

 

}

 

}

 

if (status == 0) {

 

if (!spidev->buffer) {

 

spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);

 

if (!spidev->buffer) {

 

dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");

 

status = -ENOMEM;

 

}

 

}

 

if (status == 0) {

 

spidev->users++;

 

filp->private_data = spidev;

 

backup_filp->private_data = spidev;                   /* Kiran , to use this filp in kthread to do spi_read*/

 

nonseekable_open(inode, filp);

 

 

 

}

 

} else

 

pr_debug("spidev: nothing for minor %d\n", iminor(inode));

 

mutex_unlock(&device_list_lock);

 

return status;

 

}

 

 

 

Please see the spi_read part in the FPGA kernel . Are there any problems with the code ?  Do you mean I can not use

 

filp->private_data  for reading ?

 

 

QuoteReplyEditDelete

 

 

2008-08-19 14:40:17     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Mike Frysinger (UNITED STATES)

Message: 60666   

 

you cannot use random pointers if you havent set things up.  if you havent opened any files, then you dont have any structures.  just use hardcoded buffers to test things.  otherwise you need to write a real cdev device so that userspace can read/write data which the kernel would work off of.

QuoteReplyEditDelete

 

 

2008-08-19 15:15:22     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Kiran Kumar B (INDIA)

Message: 60668   

 

Thanks Mike,  as you said right, in the user space I need to open  SPI device for the structure to be available for read / write ...  I tried the same , but  was getting an ' kerenl panic ' exception , even if I open a SPI device from user application... There should be some problem with open, let me try fixing it...  Below is the call trace for reference....

 

Call Trace:

[<00039da0>] _chrdev_open+0x44/0x170

[<00039eb0>] _chrdev_open+0x154/0x170

[<000361d6>] ___dentry_open+0xd6/0x188

[<00039d5c>] _chrdev_open+0x0/0x170

[<000362f0>] _nameidata_to_filp+0x20/0x34

[<00036334>] _do_filp_open+0x30/0x3c

[<0003607e>] _get_unused_fd+0x46/0xc8

[<00036376>] _do_sys_open+0x36/0xa8

[<00037e7c>] _sys_write+0x34/0x54

[<00036404>] _sys_open+0x18/0x20

[<000363ec>] _sys_open+0x0/0x20

[<00008000>] _l1_data_B_sram_free+0x10/0x54

 

 

Its seen that the "name of the device" passed by user during pen will be converted to filp   and an unsued fd will be allocated to the new device . I think I might have problems in my open system call, doing this..!!

 

Once I am able to successfully open device from user space...   I will try read call through kThread... Hope my approach is right.. ?   As U said I will hardcode few things presently... my longer goals is actually to implement  CDEV, but these experiments are for trials... ( building blocks for CDEV ! )

 

 

QuoteReplyEditDelete

 

 

2008-08-19 16:00:53     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Mike Frysinger (UNITED STATES)

Message: 60675   

 

the process has information about the file being accessed, not the kernel thread

 

the spidev driver is a bit complicated as it's a generic framework designed to support an open ended scenario ... best if you start with a simpler cdev driver ... you can find some in the wiki (like the simple gpio driver)

QuoteReplyEditDelete

 

 

2008-10-29 13:51:05     Re: Latency in SPI User Mode Drivers using irq_proc_handler.

Mike Frysinger (UNITED STATES)

Message: 64373   

 

the driver you refer to is not in mainline and never has been.  you cant expect it to work.

 

i just tested UIO in the current svn trunk and it should work fine.

 

root:/> lsuio -v

uio0: name=STAMP-PB5, version=123, events=4

        Device attributes:

        uevent=DRIVER=uio_pdrv_genirq

        modalias=platform:uio_pdrv_genirq

root:/> cat /proc/interrupts

  6:       5258   Blackfin Core Timer

20:          0   BFIN_SPI_DMA

21:          0   BFIN_UART_RX

22:       2343   BFIN_UART_TX

38:          0   STAMP-PB5

40:          1   eth0

Err:          0

root:/> echo 1111 > enable

root:/> dd if=enable of=/dev/uio0 bs=4 count=1

1+0 records in

1+0 records out

root:/> dd if=/dev/uio0 of=/dev/null bs=4 count=1

<userspace sleeps here until i push PB1 on the STAMP board>

1+0 records in

1+0 records out

root:/> cat /proc/interrupts

  6:     462873   Blackfin Core Timer

20:          0   BFIN_SPI_DMA

21:          0   BFIN_UART_RX

22:       6696   BFIN_UART_TX

38:          1   STAMP-PB5

40:         82   eth0

Err:          0

 

 

only change needed is to enable the driver "Userspace I/O platform driver with generic IRQ handling" and then add this to my board resources:

 

--- arch/blackfin/mach-bf533/boards/stamp.c     (revision 5504)

+++ arch/blackfin/mach-bf533/boards/stamp.c     (working copy)

@@ -38,6 +38,7 @@

#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)

#include <linux/usb/isp1362.h>

#endif

+#include <linux/uio_driver.h>

#include <linux/irq.h>

#include <linux/i2c.h>

#include <asm/dma.h>

@@ -160,6 +161,20 @@ static struct platform_device stamp_flas

};

#endif

 

+struct uio_info uio_info_push_button = {

+       .name = "STAMP-PB5",

+       .version = "123",

+       .irq = IRQ_PF5,

+       .irq_flags = IRQF_TRIGGER_RISING,

+};

+static struct platform_device uio_push_button = {

+       .name           = "uio_pdrv_genirq",

+       .id             = 0,

+       .dev = {

+               .platform_data  = &uio_info_push_button,

+       },

+};

+

#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)

static struct mtd_partition bfin_spi_flash_partitions[] = {

        {

@@ -558,6 +573,8 @@ static struct platform_device *stamp_dev

#if defined(CONFIG_MTD_BFIN_ASYNC) || defined(CONFIG_MTD_BFIN_ASYNC_MODULE)

        &stamp_flash_device,

#endif

+

+       &uio_push_button,

};

 

static int __init stamp_init(void)

Attachments

    Outcomes